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