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