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 /* */
30 /* FUNCTION RELEASE */
31 /* */
32 /* _nx_secure_x509_extended_key_usage_extension_parse PORTABLE C */
33 /* 6.1.6 */
34 /* AUTHOR */
35 /* */
36 /* Timothy Stapko, Microsoft Corporation */
37 /* */
38 /* DESCRIPTION */
39 /* */
40 /* This function parses through an X.509 certificate for an Extended */
41 /* KeyUsage extension for a a specific key usage provided by the */
42 /* caller. If the extension is not found or if the specified usage is */
43 /* not present in the extension, an error is returned. */
44 /* */
45 /* INPUT */
46 /* */
47 /* certificate Pointer to X.509 certificate */
48 /* key_usage Key usage OID to find */
49 /* */
50 /* OUTPUT */
51 /* */
52 /* status Completion status */
53 /* */
54 /* CALLS */
55 /* */
56 /* _nx_secure_x509_asn1_tlv_block_parse Parse ASN.1 block */
57 /* _nx_secure_x509_extension_find Find extension in certificate */
58 /* _nx_secure_x509_oid_parse Parse OID in certificate */
59 /* */
60 /* CALLED BY */
61 /* */
62 /* Application Code */
63 /* */
64 /* RELEASE HISTORY */
65 /* */
66 /* DATE NAME DESCRIPTION */
67 /* */
68 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
69 /* 09-30-2020 Timothy Stapko Modified comment(s), */
70 /* resulting in version 6.1 */
71 /* 04-02-2021 Timothy Stapko Modified comment(s), */
72 /* removed dependency on TLS, */
73 /* resulting in version 6.1.6 */
74 /* */
75 /**************************************************************************/
_nx_secure_x509_extended_key_usage_extension_parse(NX_SECURE_X509_CERT * certificate,UINT key_usage)76 UINT _nx_secure_x509_extended_key_usage_extension_parse(NX_SECURE_X509_CERT *certificate,
77 UINT key_usage)
78 {
79 USHORT tlv_type;
80 USHORT tlv_type_class;
81 ULONG tlv_length;
82 const UCHAR *tlv_data;
83 const UCHAR *current_buffer;
84 ULONG length;
85 ULONG header_length;
86 UINT status;
87 UINT usage_oid;
88 NX_SECURE_X509_EXTENSION key_usage_extension;
89
90 /* Find and parse the keyUsage extension. */
91 /* ExtendedKeyUsage ASN.1 format:
92
93 id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 }
94
95 ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
96
97 KeyPurposeId ::= OBJECT IDENTIFIER
98
99 */
100
101 /* Find the KeyUsage extension in the certificate. */
102 status = _nx_secure_x509_extension_find(certificate, &key_usage_extension, NX_SECURE_TLS_X509_TYPE_EXTENDED_KEY_USAGE);
103
104 /* See if extension present - it is OK if not present! */
105 if (status != NX_SECURE_X509_SUCCESS)
106 {
107 return(status);
108 }
109
110 /* The length of our extensions is the length of the sequence. */
111 current_buffer = key_usage_extension.nx_secure_x509_extension_data;
112 length = key_usage_extension.nx_secure_x509_extension_data_length;
113
114 /* Parse the sequence. */
115 status = _nx_secure_x509_asn1_tlv_block_parse(current_buffer, &length, &tlv_type, &tlv_type_class, &tlv_length, &tlv_data, &header_length);
116
117 /* Make sure we parsed the block alright. */
118 if (status != 0)
119 {
120 return(status);
121 }
122
123 /* If the next item up is not a sequence, then it isn't an extensions block. */
124 if (!(tlv_type_class == NX_SECURE_ASN_TAG_CLASS_UNIVERSAL && tlv_type == NX_SECURE_ASN_TAG_SEQUENCE))
125 {
126 /* We were expecting a bitfield but got something else. */
127 return(NX_SECURE_X509_INVALID_EXTENSION_SEQUENCE);
128 }
129
130 /* The names are in the body of the sequence structure, so use our tlv_data and length. */
131 current_buffer = tlv_data;
132 length = tlv_length;
133
134 /* Loop through OIDs to find the one we are looking for. */
135 while (length > 0)
136 {
137 /* First, parse the OID tag (if it exists). */
138 status = _nx_secure_x509_asn1_tlv_block_parse(current_buffer, &length, &tlv_type, &tlv_type_class, &tlv_length, &tlv_data, &header_length);
139
140 /* Make sure we parsed the block alright. */
141 if (status != 0)
142 {
143 return(status);
144 }
145
146 /* If the sequence does not contain OIDs, error. */
147 if (!(tlv_type_class == NX_SECURE_ASN_TAG_CLASS_UNIVERSAL && tlv_type == NX_SECURE_ASN_TAG_OID))
148 {
149 return(NX_SECURE_X509_INVALID_EXTENSION_SEQUENCE);
150 }
151
152 current_buffer += header_length;
153
154 /* The OID is in the data we extracted. */
155 _nx_secure_x509_oid_parse(tlv_data, tlv_length, &usage_oid);
156
157 /* If our OID matches the passed-in key usage OID type, success! */
158 if (usage_oid == key_usage)
159 {
160 return(NX_SECURE_X509_SUCCESS);
161 }
162
163 current_buffer += tlv_length;
164 }
165
166 /* Got through the entire list but didn't find the specified key usage. */
167 return(NX_SECURE_X509_EXT_KEY_USAGE_NOT_FOUND);
168 }
169
170