1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Secure Component */
16 /** */
17 /** X.509 Digital Certificates */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SECURE_SOURCE_CODE
23
24 #include "nx_secure_x509.h"
25
26
27 /**************************************************************************/
28 /* */
29 /* FUNCTION RELEASE */
30 /* */
31 /* _nx_secure_x509_key_usage_extension_parse PORTABLE C */
32 /* 6.1.6 */
33 /* AUTHOR */
34 /* */
35 /* Timothy Stapko, Microsoft Corporation */
36 /* */
37 /* DESCRIPTION */
38 /* */
39 /* This function parses through an X.509 certificate keyUsage */
40 /* extension and returns the Authentication Key Usage bitfield for use */
41 /* by the application. */
42 /* */
43 /* INPUT */
44 /* */
45 /* certificate Pointer to X.509 certificate */
46 /* bitfield keyUsage bitfield return */
47 /* */
48 /* OUTPUT */
49 /* */
50 /* status Completion status */
51 /* */
52 /* CALLS */
53 /* */
54 /* _nx_secure_x509_asn1_tlv_block_parse Parse ASN.1 block */
55 /* _nx_secure_x509_extension_find Find extension in certificate */
56 /* */
57 /* CALLED BY */
58 /* */
59 /* Application Code */
60 /* */
61 /* RELEASE HISTORY */
62 /* */
63 /* DATE NAME DESCRIPTION */
64 /* */
65 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
66 /* 09-30-2020 Timothy Stapko Modified comment(s), */
67 /* fixed parsing issue, */
68 /* resulting in version 6.1 */
69 /* 04-02-2021 Timothy Stapko Modified comment(s), */
70 /* removed dependency on TLS, */
71 /* resulting in version 6.1.6 */
72 /* */
73 /**************************************************************************/
_nx_secure_x509_key_usage_extension_parse(NX_SECURE_X509_CERT * certificate,USHORT * bitfield)74 UINT _nx_secure_x509_key_usage_extension_parse(NX_SECURE_X509_CERT *certificate, USHORT *bitfield)
75 {
76 USHORT tlv_type;
77 USHORT tlv_type_class;
78 ULONG tlv_length;
79 const UCHAR *tlv_data;
80 const UCHAR *current_buffer;
81 ULONG length;
82 ULONG header_length;
83 UINT status;
84 NX_SECURE_X509_EXTENSION key_usage_extension;
85
86 /* Find and parse the keyUsage extension. */
87 /* keyUsage ASN.1 format:
88
89 id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
90
91 KeyUsage ::= BIT STRING {
92 digitalSignature (0),
93 nonRepudiation (1), -- recent editions of X.509 have
94 -- renamed this bit to contentCommitment
95 keyEncipherment (2),
96 dataEncipherment (3),
97 keyAgreement (4),
98 keyCertSign (5),
99 cRLSign (6),
100 encipherOnly (7),
101 decipherOnly (8) }
102 */
103
104 /* Find the KeyUsage extension in the certificate. */
105 status = _nx_secure_x509_extension_find(certificate, &key_usage_extension, NX_SECURE_TLS_X509_TYPE_KEY_USAGE);
106
107 /* See if extension present - it is OK if not present! */
108 if (status != NX_SECURE_X509_SUCCESS)
109 {
110 return(status);
111 }
112
113 /* The length of our extensions is the length of the sequence. */
114 current_buffer = key_usage_extension.nx_secure_x509_extension_data;
115 length = key_usage_extension.nx_secure_x509_extension_data_length;
116
117 /* Parse the bit string. */
118 status = _nx_secure_x509_asn1_tlv_block_parse(current_buffer, &length, &tlv_type, &tlv_type_class, &tlv_length, &tlv_data, &header_length);
119
120 /* Make sure we parsed the block alright. */
121 if (status != 0)
122 {
123 return(status);
124 }
125
126 /* If the next item up is not a sequence, then it isn't an extensions block. */
127 if (!(tlv_type_class == NX_SECURE_ASN_TAG_CLASS_UNIVERSAL && tlv_type == NX_SECURE_ASN_TAG_BIT_STRING))
128 {
129 /* We were expecting a bitfield but got something else. */
130 return(NX_SECURE_X509_INVALID_EXTENSION_SEQUENCE);
131 }
132
133 /* Check the bit string length. */
134 if (tlv_length > sizeof(USHORT) || tlv_length < 2)
135 {
136 return(NX_SECURE_X509_INVALID_EXTENSION_SEQUENCE);
137 }
138
139 /* DER-encoding of a BIT STRING with flag values uses the top octet of the 2 byte string
140 to encode the number of 0 bits at the end of the lower octet. Thus, we need to extract
141 the top byte and shift the bottom byte to get the actual bitfield value. */
142 *bitfield = (USHORT)((tlv_data[1] << 8) + tlv_data[0]);
143
144
145 return(NX_SECURE_X509_SUCCESS);
146 }
147
148