SYNOPSIS
#include <openssl/pem.h>
EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid,
char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid,
char *kstr, int klen,
pem_password_cb *cb, void *u);
EVP_PKEY *PEM_read_bio_PUBKEY(BIO *bp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
EVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_PUBKEY(BIO *bp, EVP_PKEY *x);
int PEM_write_PUBKEY(FILE *fp, EVP_PKEY *x);
RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **x,
pem_password_cb *cb, void *u);
RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_RSAPrivateKey(BIO *bp, RSA *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_RSAPrivateKey(FILE *fp, RSA *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
RSA *PEM_read_bio_RSAPublicKey(BIO *bp, RSA **x,
pem_password_cb *cb, void *u);
RSA *PEM_read_RSAPublicKey(FILE *fp, RSA **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_RSAPublicKey(BIO *bp, RSA *x);
int PEM_write_RSAPublicKey(FILE *fp, RSA *x);
RSA *PEM_read_bio_RSA_PUBKEY(BIO *bp, RSA **x,
pem_password_cb *cb, void *u);
RSA *PEM_read_RSA_PUBKEY(FILE *fp, RSA **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_RSA_PUBKEY(BIO *bp, RSA *x);
int PEM_write_RSA_PUBKEY(FILE *fp, RSA *x);
DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **x,
pem_password_cb *cb, void *u);
DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_DSAPrivateKey(BIO *bp, DSA *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_DSAPrivateKey(FILE *fp, DSA *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
DSA *PEM_read_bio_DSA_PUBKEY(BIO *bp, DSA **x,
pem_password_cb *cb, void *u);
DSA *PEM_read_DSA_PUBKEY(FILE *fp, DSA **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_DSA_PUBKEY(BIO *bp, DSA *x);
int PEM_write_DSA_PUBKEY(FILE *fp, DSA *x);
DSA *PEM_read_bio_DSAparams(BIO *bp, DSA **x, pem_password_cb *cb, void *u);
DSA *PEM_read_DSAparams(FILE *fp, DSA **x, pem_password_cb *cb, void *u);
int PEM_write_bio_DSAparams(BIO *bp, DSA *x);
int PEM_write_DSAparams(FILE *fp, DSA *x);
DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u);
DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u);
int PEM_write_bio_DHparams(BIO *bp, DH *x);
int PEM_write_DHparams(FILE *fp, DH *x);
X509 *PEM_read_bio_X509(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
X509 *PEM_read_X509(FILE *fp, X509 **x, pem_password_cb *cb, void *u);
int PEM_write_bio_X509(BIO *bp, X509 *x);
int PEM_write_X509(FILE *fp, X509 *x);
X509 *PEM_read_bio_X509_AUX(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
X509 *PEM_read_X509_AUX(FILE *fp, X509 **x, pem_password_cb *cb, void *u);
int PEM_write_bio_X509_AUX(BIO *bp, X509 *x);
int PEM_write_X509_AUX(FILE *fp, X509 *x);
X509_REQ *PEM_read_bio_X509_REQ(BIO *bp, X509_REQ **x,
pem_password_cb *cb, void *u);
X509_REQ *PEM_read_X509_REQ(FILE *fp, X509_REQ **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_X509_REQ(BIO *bp, X509_REQ *x);
int PEM_write_X509_REQ(FILE *fp, X509_REQ *x);
int PEM_write_bio_X509_REQ_NEW(BIO *bp, X509_REQ *x);
int PEM_write_X509_REQ_NEW(FILE *fp, X509_REQ *x);
X509_CRL *PEM_read_bio_X509_CRL(BIO *bp, X509_CRL **x,
pem_password_cb *cb, void *u);
X509_CRL *PEM_read_X509_CRL(FILE *fp, X509_CRL **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_X509_CRL(BIO *bp, X509_CRL *x);
int PEM_write_X509_CRL(FILE *fp, X509_CRL *x);
PKCS7 *PEM_read_bio_PKCS7(BIO *bp, PKCS7 **x, pem_password_cb *cb, void *u);
PKCS7 *PEM_read_PKCS7(FILE *fp, PKCS7 **x, pem_password_cb *cb, void *u);
int PEM_write_bio_PKCS7(BIO *bp, PKCS7 *x);
int PEM_write_PKCS7(FILE *fp, PKCS7 *x);
NETSCAPE_CERT_SEQUENCE *PEM_read_bio_NETSCAPE_CERT_SEQUENCE(BIO *bp,
NETSCAPE_CERT_SEQUENCE **x,
pem_password_cb *cb, void *u);
NETSCAPE_CERT_SEQUENCE *PEM_read_NETSCAPE_CERT_SEQUENCE(FILE *fp,
NETSCAPE_CERT_SEQUENCE **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_NETSCAPE_CERT_SEQUENCE(BIO *bp, NETSCAPE_CERT_SEQUENCE *x);
int PEM_write_NETSCAPE_CERT_SEQUENCE(FILE *fp, NETSCAPE_CERT_SEQUENCE *x);
DESCRIPTION
Les fonctions lisent ou écrivent des structures au format En ce sens, le format est simplement des données chiffrées en base64 entourées de lignes d'en-tête.Pour plus de détails sur la signification des arguments, voir la partie .
Chaque opération possède 4 fonctions qui lui sont associées. Pour clarifier le terme « fonctions foobar » sera utilisé pour faire collectivement référence aux fonctions PEM_read_bio_foobar(), PEM_read_foobar(), PEM_write_bio_foobar() et PEM_write_foobar()
La fonction PrivateKey lit et écrit une clé privée dans le format en utilisant une structure Les routines d'écriture utilisent une clé privée au format « traditionnel » et peuvent gérer les clés privées et Les fonctions de lecture peuvent aussi gérer de façon transparente les clés chiffrées et déchiffrées au format PKCS#8.
PEM_write_bio_PKCS8PrivateKey() et PEM_write_PKCS8PrivateKey() écrivent une clé privée dans une structure dans le format PKCS#8 EncryptedPrivateKeyInfo en utilisant un algorithme de mot de passe basé sur PKCS#5 v2.0. L'argument cipher spécifie l'algorithme de chiffrement à utiliser : contrairement à toutes les autres routines le chiffrement est appliqué au niveau du PKCS#8 et pas dans les en-têtes Si cipher est alors il n'y aura pas de chiffrement utilisé et une structure PKCS#8 PrivateKeyInfo sera utilisée.
PEM_write_bio_PKCS8PrivateKey_nid() et PEM_write_PKCS8PrivateKey_nid() écrivent aussi une clé privée comme PKCS#8 EncryptedPrivateKeyInfo cependant elles utilisent les algorithmes de chiffrement KCS#5 v1.5 ou PKCS#12 à la place. L'algorithme à utiliser dans le paramètre nid doit être le de l''(voir la section ).
Les fonctions traitent une clé publique en utilisant une structure La clé publique est chiffrée comme une structure SubjectPublicKeyInfo.
Les fonctions RSAPrivateKey traitent une clé privée en utilisant une structure Elles gèrent le même format que les fonctions PrivateKey mais une erreur se produit si la clé privée n'est pas une clé
Les fonctions RSAPublicKey traitent une clé publique en utilisant une structure La clé publique est chiffrée en utilisant une structure PKCS#1 RSAPublicKey
Les fonctions traitent aussi une clé publique en utilisant une structure Mais la clé publique est chiffrée en utilisant une structure SubjectPublicKeyInfo et une erreur se produit si la clé publique n'est pas une clé
Les fonctions DSAPrivateKey traitent une clé privée en utilisant une structure Elles gèrent les mêmes formats que les fonctions PrivateKey mais une erreur se produit si la clé privée n'est pas une clé
Les fonctions traitent une clé publique en utilisant une structure La clé publique est chiffrée en utilisant une structure SubjectPublicKeyInfo et une erreur se produit si la clé publique n'est pas une clé
Les fonctions DSAparams traitent les paramètres en utilisant une structure Les paramètres sont chiffrés en utilisant une structure Dss-Parms telle que définie dans la
Les fonctions DHparams traitent les paramètres en utilisant une structure Les paramètres sont chiffrés en utilisant une structure PKCS#3 DHparameter
Les fonctions X509 traitent un certificat X509 en utilisant une structure X509. Elles traitent aussi les certificats X509 certifiés mais les paramètres de réglages sont ignorés.
Les fonctions X509_AUX traitent un certificat X509 certifié en utilisant une structure X509.
Les fonctions X509_REQ et X509_REQ_NEW traitent une requête de certificat PKCS#10 en utilisant une structure X509_REQ. La fonction d'écriture X509_REQ utilise dans l'en-tête alors que les fonctions X509_REQ_NEW utilisent (comme requis par des ). Les fonctions de lecture X509_REQ peuvent gérer les deux formes, il n'y a donc pas de fonctions de lecture X509_REQ_NEW.
Les fonctions X509_CRL traitent un en utilisant une structure X509_CRL.
Les fonctions traitent un PKCS#7 ContentInfo en utilisant une structure
Les fonctions traitent une séquence de certificats Netscape en utilisant une structure
ARGUMENTS DES FONCTIONS PEM
Les fonctions ont beaucoup d'arguments en commun.Les paramètres bp (si présents) spécifient le dans lequel il faut lire ou écrire.
Le paramètre de fp (si présent) spécifie le pointeur de dans lequel il faut lire ou écrire.
Les fonctions de lecture prennent toutes un argument **x et renvoient toutes un pointeur *, où est une structure quelconque que la fonction utilise. Si x est alors le paramètre est ignoré. Si x n'est pas mais *x est alors la structure renvoyée sera écrite dans *x. Si ni x et *x ne sont alors une tentative de réutilisation de la structure sera faite (mais voir la partie et ). Quelle que soit la valeur de x, un pointeur vers une structure est toujours renvoyé (ou en cas d'erreur).
Les fonctions qui utilisent des clés privées prennent un paramètre enc qui spécifie l'algorithme de chiffrement à utiliser, le chiffrement est fait au niveau du Si ce paramètre est mis à alors la clé privée est écrite de façon non chiffrée.
L'argument cb est le rappel à utiliser pour les requêtes pour le mot de passe utilisé pour chiffrer les structures (que des clés privées normalement).
Pour les routines d'écritures si le paramètre kstr n'est pas alors klen octets à kstr sont utilisés comme mot de passe et cb est ignoré.
Si les paramètres cb sont initialisés à et que le paramètre u n'est pas alors le paramètre u n'est pas correctement interprété comme une chaîne de caractère terminée par un null à utiliser comme mot de passe. Si cb et u sont alors la routine de retour est utilisée, ce qui affiche généralement une demande d'entrée de texte pour le mot de passe sur le terminal courant et sans affichage de l'entrée.
Le rappel du mot de passe par défaut n'est parfois pas approprié (par exemple dans une application à interface graphique), une alternative peut donc être fournie. La routine de retour de fonction a la forme suivante :
int cb(char *buf, int size, int rwflag, void *u);
buf est le tampon d'écriture dans lequel sera écrit le mot de passe. size est la taille maximale du mot de passe (c'est-à-dire la taille du tampon). rwflag est un drapeau qui est mis à 0 lors d'une lecture et à 1 lors d'une écriture. Une routine typique demandera à l'utilisateur de vérifier le mot de passe (par exemple pour le demander deux fois) si rwflagest à 1. Le paramètre u a la même valeur que le paramètre u passé à la routine Il autorise l'application à passer des données arbitraires à la rétroaction (par exemple un gestionnaire de fenêtres dans une application à interface graphique). La rétroaction doit renvoyer le nombre de caractères dans le mot de passe ou 0 en cas d'erreur.
EXEMPLES
Bien que les routines prennent plusieurs arguments, dans presque toutes leurs applications ceux-ci sont mis à 0 ouLire un certificat dans le format à partir d'un
X509 *x;
x = PEM_read_bio_X509(bp, NULL, 0, NULL);
if (x == NULL)
{
/* Erreur */
}
Méthodes alternatives :
X509 *x = NULL;
if (!PEM_read_bio_X509(bp, &x, 0, NULL))
{
/* Erreur */
}
Écrire un certificat dans un
if (!PEM_write_bio_X509(bp, x))
{
/* Erreur */
}
Écrire une clé non chiffrée dans un pointeur
if (!PEM_write_PrivateKey(fp, key, NULL, NULL, 0, 0, NULL))
{
/* Erreur */
}
Écrire une clé privée (en utilisant le format traditionnel) dans un en utilisant un chiffrement Triple-DES, le mot de passe est requis :
if (!PEM_write_bio_PrivateKey(bp, key, EVP_des_ede3_cbc(), NULL, 0, 0, NULL))
{
/* Erreur */
}
Écrire une clé privée (en utilisant le format PKCS#8) dans un en utilisant le chiffrement Triple-DES, en utilisant le mot de passe « hello » :
if (!PEM_write_bio_PKCS8PrivateKey(bp, key, EVP_des_ede3_cbc(), NULL, 0, 0, "hello"))
{
/* Erreur */
}
Lire une clé privée d'un en utilisant le mot de passe « hello » :
key = PEM_read_bio_PrivateKey(bp, NULL, 0, "hello");
if (key == NULL)
{
/* Erreur */
}
Lire une clé privée d'un en utilisant le rappel de phrase secrète :
key = PEM_read_bio_PrivateKey(bp, NULL, pass_cb, "My Private Key");
if (key == NULL)
{
/* Erreur */
}
Squelette de rappel de phrase secrète :
int pass_cb(char *buf, int size, int rwflag, void *u);
{
int len;
char *tmp;
/* On ferait probablement autre chose si 'rwflag' était à 1 */
printf("Enter pass phrase for \"%s\"\n", u);
/* obtenir la phrase chiffrée, longueur 'len' dans 'tmp' */
tmp = "hello";
len = strlen(tmp);
if (len <= 0) return 0;
/* if too long, truncate */
if (len > size) len = size;
memcpy(buf, tmp, len);
return len;
}
NOTES
Les anciennes routines d'écriture PrivateKey sont gardées pour raisons de comptabilité. Les nouvelles applications doivent écrire de nouvelles clés privées en utilisant les routines PEM_write_bio_PKCS8PrivateKey() ou PEM_write_PKCS8PrivateKey() car elles sont plus sécurisées (elles utilisent un compteur d'itération sur 2048 alors que les routines traditionnelles utilisent un compteur de 1) sauf si la compatibilité avec les anciennes versions d'OpenSSL est importante.Les routines de lecture PrivateKey peuvent être utilisées dans toutes les applications car elles manipulent tous les formats de façon transparente.
Un cas récurrent de problèmes est la tentative d'utilisation des routines de la façon suivante :
X509 *x; PEM_read_bio_X509(bp, &x, 0, NULL);
cela est un bogue car une tentative de réutilisation des données à x sera faite alors que c'est un pointeur qui n'est pas initialisé.
FORMAT DE CHIFFREMENT PEM
Cette vieille routine PrivateKey utilise une méthode non standard de chiffrement.La clé privée (ou toute autre donnée) prend la forme suivante :
-----DÉBUT CLÉ PRIVÉE RSA----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,3F17F5316E2BAC89 ...données encodées en base64... -----FIN CLÉ PRIVÉE RSA-----
La ligne qui commence DEK-Info contient deux virgules séparées par des morceaux d'information : le nom de l'algorithme de chiffrement comme utilisé par EVP_get_cipherbyname() et un salt de 8 octets chiffré comme un ensemble de valeurs hexadécimales.
Après ce sont les données chiffrées en base64.
La clé de chiffrement est déterminée en utilisant EVP_Bytestokey(), en utilisant salt et un compteur d'itération de 1. Le utilisé est la valeur de salt et *pas* le renvoyé par EVP_Bytestokey().
BOGUES
Les routines de lecture dans certaines versions d'OpenSSL, n'utiliseront pas correctement les structures existantes. De ce fait, ce qui suit :PEM_read_bio_X509(bp, &x, 0, NULL);
où x contient déjà un certificat valable, risque de ne pas fonctionner, alors que :
X509_free(x); x = PEM_read_bio_X509(bp, NULL, 0, NULL);
est garanti de fonctionner.
CODES DE RETOUR
Les routines de lectures renvoient soit un pointeur vers la structure read ou si une erreur s'est produite.La routine d'écriture renvoie 1 en cas de succès et 0 en cas d'échec.
