aboutsummaryrefslogtreecommitdiff
path: root/openssl/crypto/pem/pem_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'openssl/crypto/pem/pem_lib.c')
-rw-r--r--openssl/crypto/pem/pem_lib.c100
1 files changed, 85 insertions, 15 deletions
diff --git a/openssl/crypto/pem/pem_lib.c b/openssl/crypto/pem/pem_lib.c
index cbafefe41..42e4861bc 100644
--- a/openssl/crypto/pem/pem_lib.c
+++ b/openssl/crypto/pem/pem_lib.c
@@ -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 @@ const char PEM_version[]="PEM" OPENSSL_VERSION_PTEXT;
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 @@ int PEM_def_callback(char *buf, int num, int w, void *key)
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 @@ static int check_pem(const char *nm, const char *name)
/* 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(nm,PEM_STRING_PKCS8INF) &&
- !strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
-
- if(!strcmp(nm,PEM_STRING_RSA) &&
- !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_DSA) &&
- !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_ECPRIVATEKEY) &&
- !strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
/* Permit older strings */
if(!strcmp(nm,PEM_STRING_X509_OLD) &&
@@ -219,6 +259,14 @@ static int check_pem(const char *nm, const char *name)
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 @@ err:
#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 @@ int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
#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;
@@ -782,3 +830,25 @@ err:
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;
+ }
+