diff options
Diffstat (limited to 'crypto/asymmetric_keys/x509_cert_parser.c')
-rw-r--r-- | crypto/asymmetric_keys/x509_cert_parser.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index 7502029e3385..021d39c0ba75 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -15,10 +15,11 @@ #include <linux/slab.h> #include <linux/err.h> #include <linux/oid_registry.h> -#include <crypto/public_key.h> +#include "public_key.h" #include "x509_parser.h" #include "x509-asn1.h" #include "x509_akid-asn1.h" +#include "x509_rsakey-asn1.h" struct x509_parse_context { struct x509_certificate *cert; /* Certificate being constructed */ @@ -55,7 +56,7 @@ void x509_free_certificate(struct x509_certificate *cert) kfree(cert->akid_id); kfree(cert->akid_skid); kfree(cert->sig.digest); - kfree(cert->sig.s); + mpi_free(cert->sig.rsa.s); kfree(cert); } } @@ -102,12 +103,12 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) } } - cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL); - if (!cert->pub->key) + /* Decode the public key */ + ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, + ctx->key, ctx->key_size); + if (ret < 0) goto error_decode; - cert->pub->keylen = ctx->key_size; - /* Generate cert issuer + serial number key ID */ kid = asymmetric_key_generate_id(cert->raw_serial, cert->raw_serial_size, @@ -123,7 +124,6 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) return cert; error_decode: - kfree(cert->pub->key); kfree(ctx); error_no_ctx: x509_free_certificate(cert); @@ -404,6 +404,29 @@ int x509_extract_key_data(void *context, size_t hdrlen, return 0; } +/* + * Extract a RSA public key value + */ +int rsa_extract_mpi(void *context, size_t hdrlen, + unsigned char tag, + const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + MPI mpi; + + if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) { + pr_err("Too many public key MPIs in certificate\n"); + return -EBADMSG; + } + + mpi = mpi_read_raw_data(value, vlen); + if (!mpi) + return -ENOMEM; + + ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi; + return 0; +} + /* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */ #define SEQ_TAG_KEYID (ASN1_CONT << 6) |