In cases where we ask PEM_def_callback for minimum 0 length, accept 0 length
[openssl.git] / crypto / pem / pvkfmt.c
index 4c07aee8f2471ab0a325ad7a57cab974705204a9..281c6cd95a154c171f3bdaf17a450b767ed8465d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -66,6 +66,9 @@ static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
 # define MS_KEYTYPE_KEYX         0x1
 # define MS_KEYTYPE_SIGN         0x2
 
+/* Maximum length of a blob after header */
+# define BLOB_MAX_LENGTH          102400
+
 /* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */
 # define MS_PVKMAGIC             0xb0b5f11eL
 /* Salt length for PVK files */
@@ -117,6 +120,7 @@ static int do_blob_header(const unsigned char **in, unsigned int length,
 
     case MS_DSS1MAGIC:
         *pisdss = 1;
+        /* fall thru */
     case MS_RSA1MAGIC:
         if (*pispub == 0) {
             PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
@@ -126,6 +130,7 @@ static int do_blob_header(const unsigned char **in, unsigned int length,
 
     case MS_DSS2MAGIC:
         *pisdss = 1;
+        /* fall thru */
     case MS_RSA2MAGIC:
         if (*pispub == 1) {
             PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
@@ -211,6 +216,10 @@ static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
         return NULL;
 
     length = blob_length(bitlen, isdss, ispub);
+    if (length > BLOB_MAX_LENGTH) {
+        PEMerr(PEM_F_DO_B2I_BIO, PEM_R_HEADER_TOO_LONG);
+        return NULL;
+    }
     buf = OPENSSL_malloc(length);
     if (buf == NULL) {
         PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE);
@@ -276,14 +285,17 @@ static EVP_PKEY *b2i_dss(const unsigned char **in,
             goto memerr;
 
         BN_CTX_free(ctx);
+        ctx = NULL;
     }
     if (!DSA_set0_pqg(dsa, pbn, qbn, gbn))
         goto memerr;
     pbn = qbn = gbn = NULL;
     if (!DSA_set0_key(dsa, pub_key, priv_key))
         goto memerr;
+    pub_key = priv_key = NULL;
 
-    EVP_PKEY_set1_DSA(ret, dsa);
+    if (!EVP_PKEY_set1_DSA(ret, dsa))
+        goto memerr;
     DSA_free(dsa);
     *in = p;
     return ret;
@@ -336,12 +348,19 @@ static EVP_PKEY *b2i_rsa(const unsigned char **in,
             goto memerr;
         if (!read_lebn(&pin, nbyte, &d))
             goto memerr;
-        RSA_set0_factors(rsa, p, q);
-        RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp);
+        if (!RSA_set0_factors(rsa, p, q))
+            goto memerr;
+        p = q = NULL;
+        if (!RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp))
+            goto memerr;
+        dmp1 = dmq1 = iqmp = NULL;
     }
-    RSA_set0_key(rsa, n, e, d);
+    if (!RSA_set0_key(rsa, n, e, d))
+        goto memerr;
+    n = e = d = NULL;
 
-    EVP_PKEY_set1_RSA(ret, rsa);
+    if (!EVP_PKEY_set1_RSA(ret, rsa))
+        goto memerr;
     RSA_free(rsa);
     *in = pin;
     return ret;
@@ -425,9 +444,10 @@ static int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub)
     if (*out)
         p = *out;
     else {
-        p = OPENSSL_malloc(outlen);
-        if (p == NULL)
+        if ((p = OPENSSL_malloc(outlen)) == NULL) {
+            PEMerr(PEM_F_DO_I2B, ERR_R_MALLOC_FAILURE);
             return -1;
+        }
         *out = p;
         noinc = 1;
     }
@@ -467,7 +487,8 @@ static int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub)
 static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic)
 {
     int bitlen;
-    BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL;
+    const BIGNUM *p = NULL, *q = NULL, *g = NULL;
+    const BIGNUM *pub_key = NULL, *priv_key = NULL;
 
     DSA_get0_pqg(dsa, &p, &q, &g);
     DSA_get0_key(dsa, &pub_key, &priv_key);
@@ -494,9 +515,9 @@ static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic)
 static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
 {
     int nbyte, hnbyte, bitlen;
-    BIGNUM *e;
+    const BIGNUM *e;
 
-    RSA_get0_key(rsa, &e, NULL, NULL);
+    RSA_get0_key(rsa, NULL, &e, NULL);
     if (BN_num_bits(e) > 32)
         goto badkey;
     bitlen = RSA_bits(rsa);
@@ -506,7 +527,7 @@ static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
         *pmagic = MS_RSA1MAGIC;
         return bitlen;
     } else {
-        BIGNUM *d, *p, *q, *iqmp, *dmp1, *dmq1;
+        const BIGNUM *d, *p, *q, *iqmp, *dmp1, *dmq1;
 
         *pmagic = MS_RSA2MAGIC;
 
@@ -534,13 +555,13 @@ static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
 static void write_rsa(unsigned char **out, RSA *rsa, int ispub)
 {
     int nbyte, hnbyte;
-    BIGNUM *n, *d, *e, *p, *q, *iqmp, *dmp1, *dmq1;
+    const BIGNUM *n, *d, *e, *p, *q, *iqmp, *dmp1, *dmq1;
 
     nbyte = RSA_size(rsa);
     hnbyte = (RSA_bits(rsa) + 15) >> 4;
-    RSA_get0_key(rsa, &e, &n, &d);
+    RSA_get0_key(rsa, &n, &e, &d);
     write_lebn(out, e, 4);
-    write_lebn(out, n, -1);
+    write_lebn(out, n, nbyte);
     if (ispub)
         return;
     RSA_get0_factors(rsa, &p, &q);
@@ -556,7 +577,8 @@ static void write_rsa(unsigned char **out, RSA *rsa, int ispub)
 static void write_dsa(unsigned char **out, DSA *dsa, int ispub)
 {
     int nbyte;
-    BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL;
+    const BIGNUM *p = NULL, *q = NULL, *g = NULL;
+    const BIGNUM *pub_key = NULL, *priv_key = NULL;
 
     DSA_get0_pqg(dsa, &p, &q, &g);
     DSA_get0_key(dsa, &pub_key, &priv_key);
@@ -664,7 +686,7 @@ static EVP_PKEY *do_PVK_body(const unsigned char **in,
             inlen = cb(psbuf, PEM_BUFSIZE, 0, u);
         else
             inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
-        if (inlen <= 0) {
+        if (inlen < 0) {
             PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_PASSWORD_READ);
             goto err;
         }
@@ -757,7 +779,7 @@ static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
                    pem_password_cb *cb, void *u)
 {
     int outlen = 24, pklen;
-    unsigned char *p = NULL, *salt = NULL;
+    unsigned char *p = NULL, *start = NULL, *salt = NULL;
     EVP_CIPHER_CTX *cctx = NULL;
     if (enclevel)
         outlen += PVK_SALTLEN;
@@ -770,7 +792,7 @@ static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
     if (*out != NULL) {
         p = *out;
     } else {
-        p = OPENSSL_malloc(outlen);
+        start = p = OPENSSL_malloc(outlen);
         if (p == NULL) {
             PEMerr(PEM_F_I2B_PVK, ERR_R_MALLOC_FAILURE);
             return -1;
@@ -827,14 +849,14 @@ static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
     EVP_CIPHER_CTX_free(cctx);
 
     if (*out == NULL)
-        *out = p;
+        *out = start;
 
     return outlen;
 
  error:
     EVP_CIPHER_CTX_free(cctx);
     if (*out == NULL)
-        OPENSSL_free(p);
+        OPENSSL_free(start);
     return -1;
 }