xref: /optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c (revision 8411e6ad673d20c4742ed30c785e3f5cdea54dfa)
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