Index: openssl/crypto/pem/pem_lib.c |
=================================================================== |
--- openssl/crypto/pem/pem_lib.c (revision 105093) |
+++ openssl/crypto/pem/pem_lib.c (working copy) |
@@ -57,6 +57,7 @@ |
*/ |
#include <stdio.h> |
+#include <ctype.h> |
#include "cryptlib.h" |
#include <openssl/buffer.h> |
#include <openssl/objects.h> |
@@ -65,9 +66,13 @@ |
#include <openssl/x509.h> |
#include <openssl/pem.h> |
#include <openssl/pkcs12.h> |
+#include "asn1_locl.h" |
#ifndef OPENSSL_NO_DES |
#include <openssl/des.h> |
#endif |
+#ifndef OPENSSL_NO_ENGINE |
+#include <openssl/engine.h> |
+#endif |
const char PEM_version[]="PEM" OPENSSL_VERSION_PTEXT; |
@@ -75,6 +80,7 @@ |
static int load_iv(char **fromp,unsigned char *to, int num); |
static int check_pem(const char *nm, const char *name); |
+int pem_check_suffix(const char *pem_str, const char *suffix); |
int PEM_def_callback(char *buf, int num, int w, void *key) |
{ |
@@ -99,7 +105,7 @@ |
for (;;) |
{ |
- i=EVP_read_pw_string(buf,num,prompt,w); |
+ i=EVP_read_pw_string_min(buf,MIN_LENGTH,num,prompt,w); |
if (i != 0) |
{ |
PEMerr(PEM_F_PEM_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD); |
@@ -183,20 +189,54 @@ |
/* Make PEM_STRING_EVP_PKEY match any private key */ |
- if(!strcmp(nm,PEM_STRING_PKCS8) && |
- !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; |
+ if(!strcmp(name,PEM_STRING_EVP_PKEY)) |
+ { |
+ int slen; |
+ const EVP_PKEY_ASN1_METHOD *ameth; |
+ if(!strcmp(nm,PEM_STRING_PKCS8)) |
+ return 1; |
+ if(!strcmp(nm,PEM_STRING_PKCS8INF)) |
+ return 1; |
+ slen = pem_check_suffix(nm, "PRIVATE KEY"); |
+ if (slen > 0) |
+ { |
+ /* NB: ENGINE implementations wont contain |
+ * a deprecated old private key decode function |
+ * so don't look for them. |
+ */ |
+ ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen); |
+ if (ameth && ameth->old_priv_decode) |
+ return 1; |
+ } |
+ return 0; |
+ } |
- if(!strcmp(nm,PEM_STRING_PKCS8INF) && |
- !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; |
+ if(!strcmp(name,PEM_STRING_PARAMETERS)) |
+ { |
+ int slen; |
+ const EVP_PKEY_ASN1_METHOD *ameth; |
+ slen = pem_check_suffix(nm, "PARAMETERS"); |
+ if (slen > 0) |
+ { |
+ ENGINE *e; |
+ ameth = EVP_PKEY_asn1_find_str(&e, nm, slen); |
+ if (ameth) |
+ { |
+ int r; |
+ if (ameth->param_decode) |
+ r = 1; |
+ else |
+ r = 0; |
+#ifndef OPENSSL_NO_ENGINE |
+ if (e) |
+ ENGINE_finish(e); |
+#endif |
+ return r; |
+ } |
+ } |
+ return 0; |
+ } |
- if(!strcmp(nm,PEM_STRING_RSA) && |
- !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; |
- |
- if(!strcmp(nm,PEM_STRING_DSA) && |
- !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; |
- |
- if(!strcmp(nm,PEM_STRING_ECPRIVATEKEY) && |
- !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; |
/* Permit older strings */ |
if(!strcmp(nm,PEM_STRING_X509_OLD) && |
@@ -219,6 +259,14 @@ |
if(!strcmp(nm, PEM_STRING_PKCS7_SIGNED) && |
!strcmp(name, PEM_STRING_PKCS7)) return 1; |
+#ifndef OPENSSL_NO_CMS |
+ if(!strcmp(nm, PEM_STRING_X509) && |
+ !strcmp(name, PEM_STRING_CMS)) return 1; |
+ /* Allow CMS to be read from PKCS#7 headers */ |
+ if(!strcmp(nm, PEM_STRING_PKCS7) && |
+ !strcmp(name, PEM_STRING_CMS)) return 1; |
+#endif |
+ |
return 0; |
} |
@@ -264,7 +312,7 @@ |
#ifndef OPENSSL_NO_FP_API |
int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, |
- char *x, const EVP_CIPHER *enc, unsigned char *kstr, |
+ void *x, const EVP_CIPHER *enc, unsigned char *kstr, |
int klen, pem_password_cb *callback, void *u) |
{ |
BIO *b; |
@@ -283,7 +331,7 @@ |
#endif |
int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, |
- char *x, const EVP_CIPHER *enc, unsigned char *kstr, |
+ void *x, const EVP_CIPHER *enc, unsigned char *kstr, |
int klen, pem_password_cb *callback, void *u) |
{ |
EVP_CIPHER_CTX ctx; |
@@ -434,7 +482,6 @@ |
int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) |
{ |
- int o; |
const EVP_CIPHER *enc=NULL; |
char *p,c; |
char **header_pp = &header; |
@@ -474,7 +521,6 @@ |
header++; |
} |
*header='\0'; |
- o=OBJ_sn2nid(p); |
cipher->cipher=enc=EVP_get_cipherbyname(p); |
*header=c; |
header++; |
@@ -782,3 +828,25 @@ |
BUF_MEM_free(dataB); |
return(0); |
} |
+ |
+/* Check pem string and return prefix length. |
+ * If for example the pem_str == "RSA PRIVATE KEY" and suffix = "PRIVATE KEY" |
+ * the return value is 3 for the string "RSA". |
+ */ |
+ |
+int pem_check_suffix(const char *pem_str, const char *suffix) |
+ { |
+ int pem_len = strlen(pem_str); |
+ int suffix_len = strlen(suffix); |
+ const char *p; |
+ if (suffix_len + 1 >= pem_len) |
+ return 0; |
+ p = pem_str + pem_len - suffix_len; |
+ if (strcmp(p, suffix)) |
+ return 0; |
+ p--; |
+ if (*p != ' ') |
+ return 0; |
+ return p - pem_str; |
+ } |
+ |