1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 *
4 * LibTomCrypt is a library that provides various cryptographic
5 * algorithms in a highly modular and flexible manner.
6 *
7 * The library is free for all purposes without any express
8 * guarantee it works.
9 */
10 #include "tomcrypt_private.h"
11
12 /**
13 @file x509_decode_public_key_from_certificate.c
14 ASN.1 DER/X.509, decode a certificate
15 */
16
17 #ifdef LTC_DER
18
19 /* Check if it looks like a SubjectPublicKeyInfo */
20 #define LOOKS_LIKE_SPKI(l) ((l) != NULL) \
21 && ((l)->type == LTC_ASN1_SEQUENCE) \
22 && ((l)->child != NULL) \
23 && ((l)->child->type == LTC_ASN1_OBJECT_IDENTIFIER) \
24 && ((l)->next != NULL) \
25 && ((l)->next->type == LTC_ASN1_BIT_STRING)
26
27 /**
28 Try to decode the public key from a X.509 certificate
29 @param in The input buffer
30 @param inlen The length of the input buffer
31 @param algorithm One out of the enum #public_key_algorithms
32 @param param_type The parameters' type out of the enum ltc_asn1_type
33 @param parameters The parameters to include
34 @param parameters_len [in/out] The number of parameters to include
35 @param callback The callback
36 @param ctx The context passed to the callback
37 @return CRYPT_OK on success, CRYPT_NOP if no SubjectPublicKeyInfo was found
38 */
x509_decode_public_key_from_certificate(const unsigned char * in,unsigned long inlen,enum ltc_oid_id algorithm,ltc_asn1_type param_type,ltc_asn1_list * parameters,unsigned long * parameters_len,public_key_decode_cb callback,void * ctx)39 int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen,
40 enum ltc_oid_id algorithm, ltc_asn1_type param_type,
41 ltc_asn1_list* parameters, unsigned long *parameters_len,
42 public_key_decode_cb callback, void *ctx)
43 {
44 int err;
45 unsigned char *tmpbuf;
46 unsigned long tmpbuf_len, tmp_inlen;
47 ltc_asn1_list *decoded_list = NULL, *l;
48
49 LTC_ARGCHK(in != NULL);
50 LTC_ARGCHK(inlen != 0);
51
52 tmpbuf_len = inlen;
53 tmpbuf = XCALLOC(1, tmpbuf_len);
54 if (tmpbuf == NULL) {
55 err = CRYPT_MEM;
56 goto LBL_OUT;
57 }
58
59 tmp_inlen = inlen;
60 if ((err = der_decode_sequence_flexi(in, &tmp_inlen, &decoded_list)) == CRYPT_OK) {
61 l = decoded_list;
62
63 err = CRYPT_NOP;
64
65 /* Move 2 levels up in the tree
66 SEQUENCE
67 SEQUENCE
68 ...
69 */
70 if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) {
71 l = l->child;
72 if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) {
73 l = l->child;
74
75 /* Move forward in the tree until we find this combination
76 ...
77 SEQUENCE
78 SEQUENCE
79 OBJECT IDENTIFIER <some PKA OID, e.g. 1.2.840.113549.1.1.1>
80 NULL
81 BIT STRING
82 */
83 do {
84 /* The additional check for l->data is there to make sure
85 * we won't try to decode a list that has been 'shrunk'
86 */
87 if ((l->type == LTC_ASN1_SEQUENCE)
88 && (l->data != NULL)
89 && LOOKS_LIKE_SPKI(l->child)) {
90 if (algorithm == PKA_EC) {
91 err = ecc_import_subject_public_key_info(l->data, l->size, ctx);
92 } else {
93 err = x509_decode_subject_public_key_info(l->data, l->size,
94 algorithm, tmpbuf, &tmpbuf_len,
95 param_type, parameters, parameters_len);
96 if (err == CRYPT_OK) {
97 err = callback(tmpbuf, tmpbuf_len, ctx);
98 goto LBL_OUT;
99 }
100 }
101 }
102 l = l->next;
103 } while(l);
104 }
105 }
106 }
107
108 LBL_OUT:
109 if (decoded_list) der_free_sequence_flexi(decoded_list);
110 if (tmpbuf != NULL) XFREE(tmpbuf);
111
112 return err;
113 }
114
115 #endif
116
117 /* ref: $Format:%D$ */
118 /* git commit: $Format:%H$ */
119 /* commit time: $Format:%ai$ */
120