summaryrefslogtreecommitdiff
path: root/crypto/asymmetric_keys/x509_cert_parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/asymmetric_keys/x509_cert_parser.c')
-rw-r--r--crypto/asymmetric_keys/x509_cert_parser.c37
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)