diff options
Diffstat (limited to 'src/crypto/rsa/rsa_asn1.c')
-rw-r--r-- | src/crypto/rsa/rsa_asn1.c | 421 |
1 files changed, 381 insertions, 40 deletions
diff --git a/src/crypto/rsa/rsa_asn1.c b/src/crypto/rsa/rsa_asn1.c index 924cb8a..e3756ba 100644 --- a/src/crypto/rsa/rsa_asn1.c +++ b/src/crypto/rsa/rsa_asn1.c @@ -55,45 +55,384 @@ #include <openssl/rsa.h> +#include <assert.h> +#include <limits.h> +#include <string.h> + #include <openssl/asn1.h> #include <openssl/asn1t.h> +#include <openssl/bn.h> +#include <openssl/bytestring.h> +#include <openssl/err.h> +#include <openssl/mem.h> #include "internal.h" -/* Override the default free and new methods */ -static int rsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, - void *exarg) { - if (operation == ASN1_OP_NEW_PRE) { - *pval = (ASN1_VALUE *)RSA_new(); - if (*pval) { - return 2; +static int parse_integer_buggy(CBS *cbs, BIGNUM **out, int buggy) { + assert(*out == NULL); + *out = BN_new(); + if (*out == NULL) { + return 0; + } + if (buggy) { + return BN_cbs2unsigned_buggy(cbs, *out); + } + return BN_cbs2unsigned(cbs, *out); +} + +static int parse_integer(CBS *cbs, BIGNUM **out) { + return parse_integer_buggy(cbs, out, 0 /* not buggy */); +} + +static int marshal_integer(CBB *cbb, BIGNUM *bn) { + if (bn == NULL) { + /* An RSA object may be missing some components. */ + OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); + return 0; + } + return BN_bn2cbb(cbb, bn); +} + +static RSA *parse_public_key(CBS *cbs, int buggy) { + RSA *ret = RSA_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer_buggy(&child, &ret->n, buggy) || + !parse_integer(&child, &ret->e) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_free(ret); + return NULL; + } + return ret; +} + +RSA *RSA_parse_public_key(CBS *cbs) { + return parse_public_key(cbs, 0 /* not buggy */); +} + +RSA *RSA_parse_public_key_buggy(CBS *cbs) { + /* Estonian IDs issued between September 2014 to September 2015 are + * broken. See https://crbug.com/532048 and https://crbug.com/534766. + * + * TODO(davidben): Remove this code and callers in March 2016. */ + return parse_public_key(cbs, 1 /* buggy */); +} + +RSA *RSA_public_key_from_bytes(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + RSA *ret = RSA_parse_public_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_free(ret); + return NULL; + } + return ret; +} + +int RSA_marshal_public_key(CBB *cbb, const RSA *rsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, rsa->n) || + !marshal_integer(&child, rsa->e) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +int RSA_public_key_to_bytes(uint8_t **out_bytes, size_t *out_len, + const RSA *rsa) { + CBB cbb; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !RSA_marshal_public_key(&cbb, rsa) || + !CBB_finish(&cbb, out_bytes, out_len)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + CBB_cleanup(&cbb); + return 0; + } + return 1; +} + +/* kVersionTwoPrime and kVersionMulti are the supported values of the version + * field of an RSAPrivateKey structure (RFC 3447). */ +static const uint64_t kVersionTwoPrime = 0; +static const uint64_t kVersionMulti = 1; + +/* rsa_parse_additional_prime parses a DER-encoded OtherPrimeInfo from |cbs| and + * advances |cbs|. It returns a newly-allocated |RSA_additional_prime| on + * success or NULL on error. The |r| and |method_mod| fields of the result are + * set to NULL. */ +static RSA_additional_prime *rsa_parse_additional_prime(CBS *cbs) { + RSA_additional_prime *ret = OPENSSL_malloc(sizeof(RSA_additional_prime)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + memset(ret, 0, sizeof(RSA_additional_prime)); + + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->prime) || + !parse_integer(&child, &ret->exp) || + !parse_integer(&child, &ret->coeff) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_additional_prime_free(ret); + return NULL; + } + + return ret; +} + +RSA *RSA_parse_private_key(CBS *cbs) { + BN_CTX *ctx = NULL; + BIGNUM *product_of_primes_so_far = NULL; + RSA *ret = RSA_new(); + if (ret == NULL) { + return NULL; + } + + CBS child; + uint64_t version; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&child, &version) || + (version != kVersionTwoPrime && version != kVersionMulti) || + !parse_integer(&child, &ret->n) || + !parse_integer(&child, &ret->e) || + !parse_integer(&child, &ret->d) || + !parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->dmp1) || + !parse_integer(&child, &ret->dmq1) || + !parse_integer(&child, &ret->iqmp)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_VERSION); + goto err; + } + + /* Multi-prime RSA requires a newer version. */ + if (version == kVersionMulti && + CBS_peek_asn1_tag(&child, CBS_ASN1_SEQUENCE)) { + CBS other_prime_infos; + if (!CBS_get_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE) || + CBS_len(&other_prime_infos) == 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + goto err; + } + ret->additional_primes = sk_RSA_additional_prime_new_null(); + if (ret->additional_primes == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + ctx = BN_CTX_new(); + product_of_primes_so_far = BN_new(); + if (ctx == NULL || + product_of_primes_so_far == NULL || + !BN_mul(product_of_primes_so_far, ret->p, ret->q, ctx)) { + goto err; + } + + while (CBS_len(&other_prime_infos) > 0) { + RSA_additional_prime *ap = rsa_parse_additional_prime(&other_prime_infos); + if (ap == NULL) { + goto err; + } + if (!sk_RSA_additional_prime_push(ret->additional_primes, ap)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + RSA_additional_prime_free(ap); + goto err; + } + ap->r = BN_dup(product_of_primes_so_far); + if (ap->r == NULL || + !BN_mul(product_of_primes_so_far, product_of_primes_so_far, + ap->prime, ctx)) { + goto err; + } } + } + + if (CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + goto err; + } + + BN_CTX_free(ctx); + BN_free(product_of_primes_so_far); + return ret; + +err: + BN_CTX_free(ctx); + BN_free(product_of_primes_so_far); + RSA_free(ret); + return NULL; +} + +RSA *RSA_private_key_from_bytes(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + RSA *ret = RSA_parse_private_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_free(ret); + return NULL; + } + return ret; +} + +int RSA_marshal_private_key(CBB *cbb, const RSA *rsa) { + const int is_multiprime = + sk_RSA_additional_prime_num(rsa->additional_primes) > 0; + + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&child, + is_multiprime ? kVersionMulti : kVersionTwoPrime) || + !marshal_integer(&child, rsa->n) || + !marshal_integer(&child, rsa->e) || + !marshal_integer(&child, rsa->d) || + !marshal_integer(&child, rsa->p) || + !marshal_integer(&child, rsa->q) || + !marshal_integer(&child, rsa->dmp1) || + !marshal_integer(&child, rsa->dmq1) || + !marshal_integer(&child, rsa->iqmp)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + + if (is_multiprime) { + CBB other_prime_infos; + if (!CBB_add_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + size_t i; + for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) { + RSA_additional_prime *ap = + sk_RSA_additional_prime_value(rsa->additional_primes, i); + CBB other_prime_info; + if (!CBB_add_asn1(&other_prime_infos, &other_prime_info, + CBS_ASN1_SEQUENCE) || + !marshal_integer(&other_prime_info, ap->prime) || + !marshal_integer(&other_prime_info, ap->exp) || + !marshal_integer(&other_prime_info, ap->coeff)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + } + } + + if (!CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); return 0; - } else if (operation == ASN1_OP_FREE_PRE) { - RSA_free((RSA *)*pval); - *pval = NULL; - return 2; } return 1; } -ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = { - ASN1_SIMPLE(RSA, version, LONG), - ASN1_SIMPLE(RSA, n, BIGNUM), - ASN1_SIMPLE(RSA, e, BIGNUM), - ASN1_SIMPLE(RSA, d, BIGNUM), - ASN1_SIMPLE(RSA, p, BIGNUM), - ASN1_SIMPLE(RSA, q, BIGNUM), - ASN1_SIMPLE(RSA, dmp1, BIGNUM), - ASN1_SIMPLE(RSA, dmq1, BIGNUM), - ASN1_SIMPLE(RSA, iqmp, BIGNUM), -} ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey); +int RSA_private_key_to_bytes(uint8_t **out_bytes, size_t *out_len, + const RSA *rsa) { + CBB cbb; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !RSA_marshal_private_key(&cbb, rsa) || + !CBB_finish(&cbb, out_bytes, out_len)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + CBB_cleanup(&cbb); + return 0; + } + return 1; +} -ASN1_SEQUENCE_cb(RSAPublicKey, rsa_cb) = { - ASN1_SIMPLE(RSA, n, BIGNUM), - ASN1_SIMPLE(RSA, e, BIGNUM), -} ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey); +RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + RSA *ret = RSA_parse_public_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + RSA_free(*out); + *out = ret; + } + *inp += (size_t)len - CBS_len(&cbs); + return ret; +} + +int i2d_RSAPublicKey(const RSA *in, uint8_t **outp) { + uint8_t *der; + size_t der_len; + if (!RSA_public_key_to_bytes(&der, &der_len, in)) { + return -1; + } + if (der_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + OPENSSL_free(der); + return -1; + } + if (outp != NULL) { + if (*outp == NULL) { + *outp = der; + der = NULL; + } else { + memcpy(*outp, der, der_len); + *outp += der_len; + } + } + OPENSSL_free(der); + return (int)der_len; +} + +RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + RSA *ret = RSA_parse_private_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + RSA_free(*out); + *out = ret; + } + *inp += (size_t)len - CBS_len(&cbs); + return ret; +} + +int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp) { + uint8_t *der; + size_t der_len; + if (!RSA_private_key_to_bytes(&der, &der_len, in)) { + return -1; + } + if (der_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + OPENSSL_free(der); + return -1; + } + if (outp != NULL) { + if (*outp == NULL) { + *outp = der; + der = NULL; + } else { + memcpy(*outp, der, der_len); + *outp += der_len; + } + } + OPENSSL_free(der); + return (int)der_len; +} ASN1_SEQUENCE(RSA_PSS_PARAMS) = { ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0), @@ -104,22 +443,24 @@ ASN1_SEQUENCE(RSA_PSS_PARAMS) = { IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS); -ASN1_SEQUENCE(RSA_OAEP_PARAMS) = { - ASN1_EXP_OPT(RSA_OAEP_PARAMS, hashFunc, X509_ALGOR, 0), - ASN1_EXP_OPT(RSA_OAEP_PARAMS, maskGenFunc, X509_ALGOR, 1), - ASN1_EXP_OPT(RSA_OAEP_PARAMS, pSourceFunc, X509_ALGOR, 2), -} ASN1_SEQUENCE_END(RSA_OAEP_PARAMS); - -IMPLEMENT_ASN1_FUNCTIONS(RSA_OAEP_PARAMS); - -IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPrivateKey, RSAPrivateKey); - -IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPublicKey, RSAPublicKey); - RSA *RSAPublicKey_dup(const RSA *rsa) { - return ASN1_item_dup(ASN1_ITEM_rptr(RSAPublicKey), (RSA *) rsa); + uint8_t *der; + size_t der_len; + if (!RSA_public_key_to_bytes(&der, &der_len, rsa)) { + return NULL; + } + RSA *ret = RSA_public_key_from_bytes(der, der_len); + OPENSSL_free(der); + return ret; } RSA *RSAPrivateKey_dup(const RSA *rsa) { - return ASN1_item_dup(ASN1_ITEM_rptr(RSAPrivateKey), (RSA *) rsa); + uint8_t *der; + size_t der_len; + if (!RSA_private_key_to_bytes(&der, &der_len, rsa)) { + return NULL; + } + RSA *ret = RSA_private_key_from_bytes(der, der_len); + OPENSSL_free(der); + return ret; } |