diff options
Diffstat (limited to 'crypto/pem')
-rw-r--r-- | crypto/pem/pvkfmt.c | 190 |
1 files changed, 118 insertions, 72 deletions
diff --git a/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c index d10cf7a349..b0aa76b3f5 100644 --- a/crypto/pem/pvkfmt.c +++ b/crypto/pem/pvkfmt.c @@ -13,7 +13,7 @@ */ /* - * DSA low level APIs are deprecated for public use, but still ok for + * RSA and DSA low level APIs are deprecated for public use, but still ok for * internal use. */ #include "internal/deprecated.h" @@ -23,9 +23,8 @@ #include "crypto/pem.h" #include <openssl/rand.h> #include <openssl/bn.h> -#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) -# include <openssl/dsa.h> -# include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/rsa.h> /* * Utility function: read a DWORD (4 byte unsigned integer) in little endian @@ -36,6 +35,7 @@ static unsigned int read_ledword(const unsigned char **in) { const unsigned char *p = *in; unsigned int ret; + ret = (unsigned int)*p++; ret |= (unsigned int)*p++ << 8; ret |= (unsigned int)*p++ << 16; @@ -87,14 +87,17 @@ static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r) static EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int bitlen, int ispub); +#ifndef OPENSSL_NO_DSA static EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int bitlen, int ispub); +#endif int ossl_do_blob_header(const unsigned char **in, unsigned int length, unsigned int *pmagic, unsigned int *pbitlen, int *pisdss, int *pispub) { const unsigned char *p = *in; + if (length < 16) return 0; /* bType */ @@ -110,8 +113,9 @@ int ossl_do_blob_header(const unsigned char **in, unsigned int length, return 0; } *pispub = 0; - } else + } else { return 0; + } p++; /* Version */ if (*p++ != 0x2) { @@ -155,9 +159,9 @@ int ossl_do_blob_header(const unsigned char **in, unsigned int length, static unsigned int blob_length(unsigned bitlen, int isdss, int ispub) { - unsigned int nbyte, hnbyte; - nbyte = (bitlen + 7) >> 3; - hnbyte = (bitlen + 15) >> 4; + unsigned int nbyte = (bitlen + 7) >> 3; + unsigned int hnbyte = (bitlen + 15) >> 4; + if (isdss) { /* @@ -191,6 +195,7 @@ EVP_PKEY *ossl_b2i(const unsigned char **in, unsigned int length, int *ispub) const unsigned char *p = *in; unsigned int bitlen, magic; int isdss; + if (ossl_do_blob_header(&p, length, &magic, &bitlen, &isdss, ispub) <= 0) { ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_HEADER_PARSE_ERROR); return NULL; @@ -200,10 +205,15 @@ EVP_PKEY *ossl_b2i(const unsigned char **in, unsigned int length, int *ispub) ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT); return NULL; } - if (isdss) - return b2i_dss(&p, bitlen, *ispub); - else + if (!isdss) return b2i_rsa(&p, bitlen, *ispub); +#ifndef OPENSSL_NO_DSA + else + return b2i_dss(&p, bitlen, *ispub); +#endif + + ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return NULL; } EVP_PKEY *ossl_b2i_bio(BIO *in, int *ispub) @@ -213,6 +223,7 @@ EVP_PKEY *ossl_b2i_bio(BIO *in, int *ispub) unsigned int bitlen, magic, length; int isdss; EVP_PKEY *ret = NULL; + if (BIO_read(in, hdr_buf, 16) != 16) { ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT); return NULL; @@ -237,16 +248,22 @@ EVP_PKEY *ossl_b2i_bio(BIO *in, int *ispub) goto err; } - if (isdss) - ret = b2i_dss(&p, bitlen, *ispub); - else + if (!isdss) ret = b2i_rsa(&p, bitlen, *ispub); +#ifndef OPENSSL_NO_DSA + else + ret = b2i_dss(&p, bitlen, *ispub); +#endif + + if (ret == NULL) + ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE); err: OPENSSL_free(buf); return ret; } +#ifndef OPENSSL_NO_DSA static EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int bitlen, int ispub) { @@ -254,11 +271,9 @@ static EVP_PKEY *b2i_dss(const unsigned char **in, EVP_PKEY *ret = NULL; DSA *dsa = NULL; BN_CTX *ctx = NULL; - unsigned int nbyte; BIGNUM *pbn = NULL, *qbn = NULL, *gbn = NULL, *priv_key = NULL; BIGNUM *pub_key = NULL; - - nbyte = (bitlen + 7) >> 3; + unsigned int nbyte = (bitlen + 7) >> 3; dsa = DSA_new(); ret = EVP_PKEY_new(); @@ -321,6 +336,7 @@ static EVP_PKEY *b2i_dss(const unsigned char **in, BN_CTX_free(ctx); return NULL; } +#endif static EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int bitlen, int ispub) @@ -330,9 +346,9 @@ static EVP_PKEY *b2i_rsa(const unsigned char **in, BIGNUM *e = NULL, *n = NULL, *d = NULL; BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; RSA *rsa = NULL; - unsigned int nbyte, hnbyte; - nbyte = (bitlen + 7) >> 3; - hnbyte = (bitlen + 15) >> 4; + unsigned int nbyte = (bitlen + 7) >> 3; + unsigned int hnbyte = (bitlen + 15) >> 4; + rsa = RSA_new(); ret = EVP_PKEY_new(); if (rsa == NULL || ret == NULL) @@ -419,6 +435,7 @@ EVP_PKEY *b2i_PublicKey_bio(BIO *in) static void write_ledword(unsigned char **out, unsigned int dw) { unsigned char *p = *out; + *p++ = dw & 0xff; *p++ = (dw >> 8) & 0xff; *p++ = (dw >> 16) & 0xff; @@ -433,25 +450,29 @@ static void write_lebn(unsigned char **out, const BIGNUM *bn, int len) } static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *magic); -static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *magic); - static void write_rsa(unsigned char **out, RSA *rsa, int ispub); + +#ifndef OPENSSL_NO_DSA +static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *magic); static void write_dsa(unsigned char **out, DSA *dsa, int ispub); +#endif static int do_i2b(unsigned char **out, const EVP_PKEY *pk, int ispub) { unsigned char *p; - unsigned int bitlen, magic = 0, keyalg; + unsigned int bitlen = 0, magic = 0, keyalg = 0; int outlen, noinc = 0; int pktype = EVP_PKEY_id(pk); - if (pktype == EVP_PKEY_DSA) { - bitlen = check_bitlen_dsa(EVP_PKEY_get0_DSA(pk), ispub, &magic); - keyalg = MS_KEYALG_DSS_SIGN; - } else if (pktype == EVP_PKEY_RSA) { + + if (pktype == EVP_PKEY_RSA) { bitlen = check_bitlen_rsa(EVP_PKEY_get0_RSA(pk), ispub, &magic); keyalg = MS_KEYALG_RSA_KEYX; - } else - return -1; +#ifndef OPENSSL_NO_DSA + } else if (pktype == EVP_PKEY_DSA) { + bitlen = check_bitlen_dsa(EVP_PKEY_get0_DSA(pk), ispub, &magic); + keyalg = MS_KEYALG_DSS_SIGN; +#endif + } if (bitlen == 0) return -1; outlen = 16 + blob_length(bitlen, @@ -478,10 +499,12 @@ static int do_i2b(unsigned char **out, const EVP_PKEY *pk, int ispub) write_ledword(&p, keyalg); write_ledword(&p, magic); write_ledword(&p, bitlen); - if (keyalg == MS_KEYALG_DSS_SIGN) - write_dsa(&p, EVP_PKEY_get0_DSA(pk), ispub); - else + if (keyalg == MS_KEYALG_RSA_KEYX) write_rsa(&p, EVP_PKEY_get0_RSA(pk), ispub); +#ifndef OPENSSL_NO_DSA + else + write_dsa(&p, EVP_PKEY_get0_DSA(pk), ispub); +#endif if (!noinc) *out += outlen; return outlen; @@ -491,6 +514,7 @@ static int do_i2b_bio(BIO *out, const EVP_PKEY *pk, int ispub) { unsigned char *tmp = NULL; int outlen, wrlen; + outlen = do_i2b(&tmp, pk, ispub); if (outlen < 0) return -1; @@ -501,34 +525,6 @@ static int do_i2b_bio(BIO *out, const EVP_PKEY *pk, int ispub) return -1; } -static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic) -{ - int bitlen; - 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); - bitlen = BN_num_bits(p); - if ((bitlen & 7) || (BN_num_bits(q) != 160) - || (BN_num_bits(g) > bitlen)) - goto badkey; - if (ispub) { - if (BN_num_bits(pub_key) > bitlen) - goto badkey; - *pmagic = MS_DSS1MAGIC; - } else { - if (BN_num_bits(priv_key) > 160) - goto badkey; - *pmagic = MS_DSS2MAGIC; - } - - return bitlen; - badkey: - ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS); - return 0; -} - static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic) { int nbyte, hnbyte, bitlen; @@ -591,6 +587,35 @@ static void write_rsa(unsigned char **out, RSA *rsa, int ispub) write_lebn(out, d, nbyte); } +#ifndef OPENSSL_NO_DSA +static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic) +{ + int bitlen; + 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); + bitlen = BN_num_bits(p); + if ((bitlen & 7) || (BN_num_bits(q) != 160) + || (BN_num_bits(g) > bitlen)) + goto badkey; + if (ispub) { + if (BN_num_bits(pub_key) > bitlen) + goto badkey; + *pmagic = MS_DSS1MAGIC; + } else { + if (BN_num_bits(priv_key) > 160) + goto badkey; + *pmagic = MS_DSS2MAGIC; + } + + return bitlen; + badkey: + ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS); + return 0; +} + static void write_dsa(unsigned char **out, DSA *dsa, int ispub) { int nbyte; @@ -612,6 +637,7 @@ static void write_dsa(unsigned char **out, DSA *dsa, int ispub) *out += 24; return; } +#endif int i2b_PrivateKey_bio(BIO *out, const EVP_PKEY *pk) { @@ -623,8 +649,6 @@ int i2b_PublicKey_bio(BIO *out, const EVP_PKEY *pk) return do_i2b_bio(out, pk, 1); } -# ifndef OPENSSL_NO_RC4 - int ossl_do_PVK_header(const unsigned char **in, unsigned int length, int skip_magic, unsigned int *psaltlen, unsigned int *pkeylen) @@ -669,12 +693,14 @@ int ossl_do_PVK_header(const unsigned char **in, unsigned int length, return 1; } +#ifndef OPENSSL_NO_RC4 static int derive_pvk_key(unsigned char *key, const unsigned char *salt, unsigned int saltlen, const unsigned char *pass, int passlen) { EVP_MD_CTX *mctx = EVP_MD_CTX_new(); int rv = 1; + if (mctx == NULL || !EVP_DigestInit_ex(mctx, EVP_sha1(), NULL) || !EVP_DigestUpdate(mctx, salt, saltlen) @@ -685,6 +711,7 @@ static int derive_pvk_key(unsigned char *key, EVP_MD_CTX_free(mctx); return rv; } +#endif static EVP_PKEY *do_PVK_body(const unsigned char **in, unsigned int saltlen, unsigned int keylen, @@ -692,14 +719,17 @@ static EVP_PKEY *do_PVK_body(const unsigned char **in, { EVP_PKEY *ret = NULL; const unsigned char *p = *in; - unsigned int magic; - unsigned char *enctmp = NULL, *q; + unsigned char *enctmp = NULL; unsigned char keybuf[20]; EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new(); if (saltlen) { +#ifndef OPENSSL_NO_RC4 + unsigned int magic; char psbuf[PEM_BUFSIZE]; int enctmplen, inlen; + unsigned char *q; + if (cb) inlen = cb(psbuf, PEM_BUFSIZE, 0, u); else @@ -749,6 +779,10 @@ static EVP_PKEY *do_PVK_body(const unsigned char **in, } } p = enctmp; +#else + ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER); + goto err; +#endif } ret = b2i_PrivateKey(&p, keylen); @@ -768,6 +802,7 @@ EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u) int buflen; EVP_PKEY *ret = NULL; unsigned int saltlen, keylen; + if (BIO_read(in, pvk_hdr, 24) != 24) { ERR_raise(ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT); return NULL; @@ -798,8 +833,12 @@ static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel, pem_password_cb *cb, void *u) { int outlen = 24, pklen; - unsigned char *p = NULL, *start = NULL, *salt = NULL; + unsigned char *p = NULL, *start = NULL; EVP_CIPHER_CTX *cctx = NULL; +#ifndef OPENSSL_NO_RC4 + unsigned char *salt = NULL; +#endif + if (enclevel) outlen += PVK_SALTLEN; pklen = do_i2b(NULL, pk, 0); @@ -824,24 +863,30 @@ static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel, write_ledword(&p, MS_PVKMAGIC); write_ledword(&p, 0); - if (EVP_PKEY_id(pk) == EVP_PKEY_DSA) - write_ledword(&p, MS_KEYTYPE_SIGN); - else + if (EVP_PKEY_id(pk) == EVP_PKEY_RSA) write_ledword(&p, MS_KEYTYPE_KEYX); +#ifndef OPENSSL_NO_DSA + else + write_ledword(&p, MS_KEYTYPE_SIGN); +#endif write_ledword(&p, enclevel ? 1 : 0); write_ledword(&p, enclevel ? PVK_SALTLEN : 0); write_ledword(&p, pklen); if (enclevel) { +#ifndef OPENSSL_NO_RC4 if (RAND_bytes(p, PVK_SALTLEN) <= 0) goto error; salt = p; p += PVK_SALTLEN; +#endif } do_i2b(&p, pk, 0); if (enclevel != 0) { +#ifndef OPENSSL_NO_RC4 char psbuf[PEM_BUFSIZE]; unsigned char keybuf[20]; int enctmplen, inlen; + if (cb) inlen = cb(psbuf, PEM_BUFSIZE, 1, u); else @@ -863,6 +908,10 @@ static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel, goto error; if (!EVP_EncryptFinal_ex(cctx, p + enctmplen, &enctmplen)) goto error; +#else + ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER); + goto error; +#endif } EVP_CIPHER_CTX_free(cctx); @@ -884,6 +933,7 @@ int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel, { unsigned char *tmp = NULL; int outlen, wrlen; + outlen = i2b_PVK(&tmp, pk, enclevel, cb, u); if (outlen < 0) return -1; @@ -895,7 +945,3 @@ int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel, ERR_raise(ERR_LIB_PEM, PEM_R_BIO_WRITE_FAILURE); return -1; } - -# endif - -#endif |