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