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 /*  FUNCTION                                               RELEASE        */
29 /*                                                                        */
30 /*    _nx_secure_x509_certificate_initialize              PORTABLE C      */
31 /*                                                           6.1.7        */
32 /*  AUTHOR                                                                */
33 /*                                                                        */
34 /*    Timothy Stapko, Microsoft Corporation                               */
35 /*                                                                        */
36 /*  DESCRIPTION                                                           */
37 /*                                                                        */
38 /*      This function initializes an NX_SECURE_X509_CERT                  */
39 /*      structure with a DER-encoded X509 digital certificate, and        */
40 /*      in the case of a server or client local certificate, the          */
41 /*      associated private key.                                           */
42 /*                                                                        */
43 /*      This function takes a raw data buffer as optional input. The      */
44 /*      buffer is used to hold the un-parsed certificate data in DER      */
45 /*      encoded format. If the raw_data_buffer parameter is NX_NULL,      */
46 /*      The certificate data is referenced directly - DO NOT change       */
47 /*      the certificate data after calling this function if a separate    */
48 /*      buffer is not used or unexpected behavior may occur.              */
49 /*                                                                        */
50 /*      The private key is also optional. Some certificates (such as      */
51 /*      in the trusted store) will not have a private key. For such       */
52 /*      certificates the private key parameter should be passed as        */
53 /*      NX_NULL.                                                          */
54 /*                                                                        */
55 /*      The private key, if supplied, must have a private key type, which */
56 /*      is defined as a 32-bit value. If the top 16 bits are non-zero,    */
57 /*      the value is considered user-defined and NetX Secure will perform */
58 /*      no processing on the key data. If the top 16 bits are zero, the   */
59 /*      value defines a type known to NetX Secure that will be parsed     */
60 /*      accordingly. Unknown types in the known-value range will result   */
61 /*      in an error. No error checking will be performed on user-defined  */
62 /*      types.                                                            */
63 /*                                                                        */
64 /*  INPUT                                                                 */
65 /*                                                                        */
66 /*    certificate                           Certificate structure         */
67 /*    certificate_data                      Pointer to certificate data   */
68 /*    length                                Length of certificate data    */
69 /*    raw_data_buffer                       Buffer to hold raw cert data  */
70 /*    buffer_size                           Size of raw data buffer       */
71 /*    private_key                           Pointer to private key data   */
72 /*    priv_len                              Length of private key data    */
73 /*    private_key_type                      Type of private key data      */
74 /*                                                                        */
75 /*  OUTPUT                                                                */
76 /*                                                                        */
77 /*    status                                Completion status             */
78 /*                                                                        */
79 /*  CALLS                                                                 */
80 /*                                                                        */
81 /*    _nx_secure_x509_certificate_parse     Extract public key data       */
82 /*    _nx_secure_x509_pkcs1_rsa_private_key_parse                         */
83 /*                                          Parse RSA key (PKCS#1 format) */
84 /*    _nx_secure_x509_ec_private_key_parse  Parse EC key                  */
85 /*                                                                        */
86 /*  CALLED BY                                                             */
87 /*                                                                        */
88 /*    Application Code                                                    */
89 /*                                                                        */
90 /*  RELEASE HISTORY                                                       */
91 /*                                                                        */
92 /*    DATE              NAME                      DESCRIPTION             */
93 /*                                                                        */
94 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
95 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
96 /*                                            verified memcpy use cases,  */
97 /*                                            resulting in version 6.1    */
98 /*  03-02-2021     Timothy Stapko           Modified comment(s),          */
99 /*                                            removed unnecessary mutex,  */
100 /*                                            resulting in version 6.1.5  */
101 /*  04-02-2021     Timothy Stapko           Modified comment(s),          */
102 /*                                            removed dependency on TLS,  */
103 /*                                            resulting in version 6.1.6  */
104 /*  06-02-2021     Timothy Stapko           Modified comment(s),          */
105 /*                                            supported hardware EC       */
106 /*                                            private key,                */
107 /*                                            resulting in version 6.1.7  */
108 /*                                                                        */
109 /**************************************************************************/
_nx_secure_x509_certificate_initialize(NX_SECURE_X509_CERT * certificate,UCHAR * certificate_data,USHORT length,UCHAR * raw_data_buffer,USHORT buffer_size,const UCHAR * private_key,USHORT priv_len,UINT private_key_type)110 UINT _nx_secure_x509_certificate_initialize(NX_SECURE_X509_CERT *certificate,
111                                             UCHAR *certificate_data, USHORT length,
112                                             UCHAR *raw_data_buffer, USHORT buffer_size,
113                                             const UCHAR *private_key, USHORT priv_len,
114                                             UINT private_key_type)
115 
116 {
117 UINT status;
118 UINT bytes_processed;
119 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
120 NX_SECURE_EC_PRIVATE_KEY *ec_key;
121 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
122 
123     NX_SECURE_MEMSET(certificate, 0, sizeof(NX_SECURE_X509_CERT));
124 
125     /* Set up the certificate with raw data. */
126     certificate -> nx_secure_x509_certificate_raw_data_length = length;
127     if (raw_data_buffer == NX_CRYPTO_NULL)
128     {
129         /* No buffer was passed in so just point to the certificate itself. */
130         certificate -> nx_secure_x509_certificate_raw_buffer_size = length;
131         certificate -> nx_secure_x509_certificate_raw_data = certificate_data;
132     }
133     else
134     {
135         /* Make sure we have enough space in the buffer for the certificate. */
136         if (length > buffer_size)
137         {
138             return(NX_SECURE_X509_INSUFFICIENT_CERT_SPACE);
139         }
140         /* Use the caller-supplied buffer for the certificate. */
141         certificate -> nx_secure_x509_certificate_raw_buffer_size = buffer_size;
142         certificate -> nx_secure_x509_certificate_raw_data = raw_data_buffer;
143         NX_SECURE_MEMCPY(certificate -> nx_secure_x509_certificate_raw_data, certificate_data, length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */
144     }
145 
146     /* Parse the DER-encoded X509 certificate to extract the public key data.
147      * NOTE: All the pointers returned in the X509 cert will point into the certificate data
148      *       passed in here, so DO NOT modify the certificate data or pass in a pointer to a
149      *       temporary buffer!*/
150 
151     status = _nx_secure_x509_certificate_parse(certificate -> nx_secure_x509_certificate_raw_data,
152                                                length, &bytes_processed, certificate);
153 
154     if (status != 0)
155     {
156         return(NX_SECURE_X509_INVALID_CERTIFICATE);
157     }
158 
159     /* If the optional private key is supplied, save it for later use. */
160     if (private_key != NULL && priv_len > 0)
161     {
162         /* Save the key type for later. */
163         certificate -> nx_secure_x509_private_key_type = private_key_type;
164 
165         /* Check for user-defined key types. */
166         if ((private_key_type & NX_SECURE_X509_KEY_TYPE_USER_DEFINED_MASK) != 0x0)
167         {
168             /* User-defined, just save off the key data. */
169             certificate -> nx_secure_x509_private_key.user_key.key_data = private_key;
170             certificate -> nx_secure_x509_private_key.user_key.key_length = priv_len;
171         }
172         else
173         {
174             /* Built-in key type. Attempt to parse the key data. */
175             switch (private_key_type)
176             {
177             case NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER:
178                 status = _nx_secure_x509_pkcs1_rsa_private_key_parse(private_key, priv_len, &bytes_processed, &certificate -> nx_secure_x509_private_key.rsa_private_key);
179                 break;
180 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
181             case NX_SECURE_X509_KEY_TYPE_EC_DER:
182                 ec_key = &certificate -> nx_secure_x509_private_key.ec_private_key;
183                 status = _nx_secure_x509_ec_private_key_parse(private_key, priv_len, &bytes_processed, ec_key);
184                 break;
185 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
186 
187             case NX_SECURE_X509_KEY_TYPE_HARDWARE:
188                 certificate -> nx_secure_x509_private_key.user_key.key_data = private_key;
189                 certificate -> nx_secure_x509_private_key.user_key.key_length = priv_len;
190                 status = NX_SUCCESS;
191                 break;
192             case NX_SECURE_X509_KEY_TYPE_NONE:
193             default:
194                 /* Unknown or invalid key type, return error. */
195                 status = NX_SECURE_X509_INVALID_PRIVATE_KEY_TYPE;
196                 break;
197             }
198 
199             /* See if we had any issues in parsing. */
200             if (status != 0)
201             {
202                 return(status);
203             }
204         }
205 
206         /* We have a private key, this is a server or client identity certificate. */
207         certificate -> nx_secure_x509_certificate_is_identity_cert = NX_CRYPTO_TRUE;
208     }
209     else
210     {
211         /* No private key? Cannot be an identity certificate. */
212         certificate -> nx_secure_x509_certificate_is_identity_cert = NX_CRYPTO_FALSE;
213     }
214 
215     certificate -> nx_secure_x509_next_certificate = NULL;
216 
217     return(NX_SECURE_X509_SUCCESS);
218 }
219 
220