1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** NetX Secure Component                                                 */
17 /**                                                                       */
18 /**    X.509 Digital Certificates                                         */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #define NX_SECURE_SOURCE_CODE
24 
25 #include "nx_secure_x509.h"
26 
27 /**************************************************************************/
28 /*                                                                        */
29 /*  FUNCTION                                               RELEASE        */
30 /*                                                                        */
31 /*    _nx_secure_x509_asn1_tlv_block_parse                PORTABLE C      */
32 /*                                                           6.1.6        */
33 /*  AUTHOR                                                                */
34 /*                                                                        */
35 /*    Timothy Stapko, Microsoft Corporation                               */
36 /*                                                                        */
37 /*  DESCRIPTION                                                           */
38 /*                                                                        */
39 /*    This function parses an ASN.1 type-length-value (TLV) block for use */
40 /*    by the X509 parser.                                                 */
41 /*                                                                        */
42 /*  INPUT                                                                 */
43 /*                                                                        */
44 /*    buffer                                Pointer to data to be parsed  */
45 /*    tlv_type                              Return block type             */
46 /*    tlv_tag_class                         Return class of the tag       */
47 /*    tlv_length                            Return parsed length          */
48 /*    tlv_data                              Return pointer to block data  */
49 /*    header_length                         Return length of block itself */
50 /*                                                                        */
51 /*  OUTPUT                                                                */
52 /*                                                                        */
53 /*    status                                Completion status             */
54 /*                                                                        */
55 /*  CALLS                                                                 */
56 /*                                                                        */
57 /*    None                                                                */
58 /*                                                                        */
59 /*  CALLED BY                                                             */
60 /*                                                                        */
61 /*    _nx_secure_x509_certificate_parse     Extract public key data       */
62 /*    _nx_secure_x509_certificate_revocation_list_parse                   */
63 /*                                          Parse revocation list         */
64 /*    _nx_secure_x509_certificate_verify    Verify a certificate          */
65 /*    _nx_secure_x509_crl_extensions_parse  Parse extensions in crl       */
66 /*    _nx_secure_x509_crl_issuer_parse      Parse issuer in crl           */
67 /*    _nx_secure_x509_crl_parse_entry       Parse an entry in crl         */
68 /*    _nx_secure_x509_crl_revoked_certs_list_parse                        */
69 /*                                          Parse revoked certificate list*/
70 /*                                            in crl                      */
71 /*    _nx_secure_x509_crl_signature_algorithm_parse                       */
72 /*                                          Parse signature algorithm in  */
73 /*                                            crl                         */
74 /*    _nx_secure_x509_crl_signature_data_parse                            */
75 /*                                          Parse signature data in crl   */
76 /*    _nx_secure_x509_crl_tbscert_list_parse                              */
77 /*                                          Parse TBSCertList in crl      */
78 /*    _nx_secure_x509_crl_update_times_parse                              */
79 /*                                          Parse Update times in crl     */
80 /*    _nx_secure_x509_crl_verify            Verify revocation list        */
81 /*    _nx_secure_x509_crl_version_parse     Parse version in crl          */
82 /*    _nx_secure_x509_extended_key_usage_extension_parse                  */
83 /*                                          Parse Extended KeyUsage       */
84 /*                                            extension                   */
85 /*    _nx_secure_x509_distinguished_name_parse                            */
86 /*                                          Parse Distinguished Name      */
87 /*    _nx_secure_x509_extension_find        Find extension in certificate */
88 /*    _nx_secure_x509_extract_name_oid_data Extract Distinguished Name    */
89 /*    _nx_secure_x509_extract_oid_data      Extract OID data              */
90 /*    _nx_secure_x509_key_usage_extension_parse                           */
91 /*                                          Parse KeyUsage extension      */
92 /*    _nx_secure_x509_parse_cert_data       Parse certificate             */
93 /*    _nx_secure_x509_parse_extensions      Parse extension in certificate*/
94 /*    _nx_secure_x509_parse_issuer          Parse issuer in certificate   */
95 /*    _nx_secure_x509_parse_public_key      Parse public key in           */
96 /*                                            certificate                 */
97 /*    _nx_secure_x509_parse_serial_num      Parse serial number in        */
98 /*                                            certificate                 */
99 /*    _nx_secure_x509_parse_signature_algorithm                           */
100 /*                                          Parse signature algorithm in  */
101 /*                                            certificate                 */
102 /*    _nx_secure_x509_parse_signature_data  Parse signature data in       */
103 /*                                            certificate                 */
104 /*    _nx_secure_x509_parse_subject         Parse subject in certificate  */
105 /*    _nx_secure_x509_parse_unique_ids      Parse unique IDs in           */
106 /*                                            certificate                 */
107 /*    _nx_secure_x509_parse_validity        Parse validity in certificate */
108 /*    _nx_secure_x509_parse_version         Parse version in certificate  */
109 /*    _nx_secure_x509_pkcs1_rsa_private_key_parse                         */
110 /*                                          Parse RSA key (PKCS#1 format) */
111 /*    _nx_secure_x509_pkcs7_decode          Decode the PKCS#7 signature   */
112 /*    _nx_secure_x509_policy_qualifiers_parse                             */
113 /*                                          Parse policy qualifiers       */
114 /*    _nx_secure_x509_subject_alt_names_find                              */
115 /*                                          Find subject alt names        */
116 /*                                                                        */
117 /*  RELEASE HISTORY                                                       */
118 /*                                                                        */
119 /*    DATE              NAME                      DESCRIPTION             */
120 /*                                                                        */
121 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
122 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
123 /*                                            resulting in version 6.1    */
124 /*  04-02-2021     Timothy Stapko           Modified comment(s),          */
125 /*                                            removed dependency on TLS,  */
126 /*                                            resulting in version 6.1.6  */
127 /*                                                                        */
128 /**************************************************************************/
_nx_secure_x509_asn1_tlv_block_parse(const UCHAR * buffer,ULONG * buffer_length,USHORT * tlv_type,USHORT * tlv_tag_class,ULONG * tlv_length,const UCHAR ** tlv_data,ULONG * header_length)129 UINT _nx_secure_x509_asn1_tlv_block_parse(const UCHAR *buffer, ULONG *buffer_length, USHORT *tlv_type,
130                                           USHORT *tlv_tag_class, ULONG *tlv_length,
131                                           const UCHAR **tlv_data, ULONG *header_length)
132 {
133 UINT   current_index;
134 USHORT current_tag;
135 ULONG  length;
136 ULONG  length_bytes;
137 
138     current_index = 0;
139     current_tag = buffer[current_index];
140 
141     if (*buffer_length < 1)
142     {
143         return(NX_SECURE_X509_ASN1_LENGTH_TOO_LONG);
144     }
145 
146     /*  Handle multi-byte encoded tags. */
147     if ((current_tag & NX_SECURE_ASN_TAG_MULTIBYTE_MASK) == NX_SECURE_ASN_TAG_MULTIBYTE_MASK)
148     {
149         return(NX_SECURE_X509_MULTIBYTE_TAG_UNSUPPORTED);
150     }
151     else
152     {
153         *header_length = 1;
154         *buffer_length = *buffer_length - 1;
155     }
156 
157     /* Get the class of the tag so we can return it. */
158     *tlv_tag_class = (USHORT)((current_tag & NX_SECURE_ASN_TAG_CLASS_MASK) >> 6);
159 
160     /* Make sure we have a valid tag class. */
161     if (*tlv_tag_class == NX_SECURE_ASN_TAG_CLASS_APPLICATION ||
162         *tlv_tag_class == NX_SECURE_ASN_TAG_CLASS_PRIVATE)
163     {
164         /* The tag class is invalid, return error. */
165         return(NX_SECURE_X509_INVALID_TAG_CLASS);
166     }
167 
168     /* The caller actually handles what happens based on the tag type. */
169     if (current_tag & NX_SECURE_ASN_TAG_CONSTRUCTED_MASK)
170     {
171         current_tag = current_tag & (USHORT)(~NX_SECURE_ASN_TAG_CONSTRUCTED_MASK);
172     }
173 
174     /* Clear out the class and constructed bits before returning the tag value. */
175     *tlv_type = current_tag & NX_SECURE_ASN_TAG_MASK;
176     current_index++;
177 
178     if (*buffer_length < 1)
179     {
180         return(NX_SECURE_X509_ASN1_LENGTH_TOO_LONG);
181     }
182 
183     if (current_tag == NX_SECURE_ASN_TAG_NULL)
184     {
185         /*  If tag is NULL, there is no length byte, just a value of zero, */
186         *tlv_length = 1;
187 
188         /* Set the data pointer and return. */
189         *tlv_data = &buffer[current_index];
190 
191         return(NX_SECURE_X509_SUCCESS);
192     }
193 
194     /* Handle the length. */
195     length = buffer[current_index];
196     current_index++;
197     *header_length = *header_length + 1;
198     *buffer_length = *buffer_length - 1;
199 
200     /* Check for multi-byte length by looking at the top bit of the length byte. */
201     if (length & 0x80)
202     {
203         /* Multi-byte length:
204            > 127, high bit is set, and lower 7 bits becomes the number of following bytes of *length*
205            so 841 bytes of Value is encoded as 0x82, 0x03, 0x49 (0x82 = 2 bytes of length, 0x0349 = 841).
206          */
207 
208         /*  Mask off top bit to get the number of bytes in length. */
209         length_bytes = length & 0x7F;
210         length = 0;
211 
212         /*  Check for length too big to handle. */
213         if (length_bytes > 4 || length_bytes > *buffer_length)
214         {
215 
216             return(NX_SECURE_X509_ASN1_LENGTH_TOO_LONG);
217         }
218 
219         /* Update header length. */
220         *header_length = *header_length + length_bytes;
221         *buffer_length = *buffer_length - length_bytes;
222 
223         while (length_bytes > 0)
224         {
225             /* Shift length one byte up and add in next byte. */
226             length <<= 8;
227             length += buffer[current_index];
228 
229             /* Advance our index by one byte. */
230             current_index++;
231             length_bytes--;
232         }
233     }
234     else
235     {
236         /* Single-byte length:
237            <= 127 (7 bits), length is the number of bytes of Value */
238         *tlv_length = length;
239     }
240 
241     if (length > *buffer_length)
242     {
243         return(NX_SECURE_X509_ASN1_LENGTH_TOO_LONG);
244     }
245 
246     *buffer_length = *buffer_length - length;
247 
248     /* Set the length to return to caller. */
249     *tlv_length = length;
250 
251     /*  Now, we can set the tld value */
252     *tlv_data = &buffer[current_index];
253 
254     return(NX_SECURE_X509_SUCCESS);
255 }
256 
257