1 /*
2  * FreeRTOS V202212.00
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  */
26 
27 /* FreeRTOS includes. */
28 #include "FreeRTOS.h"
29 #include "task.h"
30 
31 /* Standard include. */
32 #include "stdio.h"
33 
34 /* PKCS #11 includes. */
35 #include "core_pkcs11_config.h"
36 #include "core_pkcs11.h"
37 #include "pkcs11.h"
38 
39 /* mbed TLS includes. */
40 #include "mbedtls/pk.h"
41 
42 /* Demo includes. */
43 #include "demo_helpers.h"
44 #include "pkcs11_demos.h"
45 
46 /* RSA certificate that has been generated off the device.
47  * This key will be used as an example for importing an object onto the device.
48  * This is useful when the device itself cannot create credentials or for storing
49  * a well known CA certificate.
50  */
51 #define pkcs11demo_RSA_CERTIFICATE                                       \
52     ""                                                                   \
53     "-----BEGIN CERTIFICATE-----\n"                                      \
54     "MIIFgTCCA2mgAwIBAgIUPsOLvI1VI8EtdIZi1s2vp7sGhy8wDQYJKoZIhvcNAQEL\n" \
55     "BQAwTzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxl\n" \
56     "MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwIBcNMjAwNzEzMTY0\n" \
57     "MDUyWhgPMjEyMDA2MTkxNjQwNTJaME8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJX\n" \
58     "QTEQMA4GA1UEBwwHU2VhdHRsZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ\n" \
59     "dHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtSrIA3Esgjtf\n" \
60     "5Ltk/zMaUIbdX8F3VJKyQ9L3Bu07BDNVYmSqPg7+TNvUSrVT7npYmF7TE+jKJXvW\n" \
61     "Lf9UUQZUb5KFf6cKkUKoZlXY3Jn3oInD9md7Yyry1z7eTrBz20UnUaTx28lqq2T8\n" \
62     "SzwAthMyjhHmXeFXTD+KKY7j9H73kgOH4EUme3Nrxp+z/yaSQN5Naeqp1/HBGayY\n" \
63     "TqFOgDlv2NXdrvKPlvBeEpWa6WoRnq7iC3jCuafO4ZUueu4hdt9tfQLXtKixLKhu\n" \
64     "Tjw1w7iKi88KjQhGz7gCDxCGQxWm22HgXdNEBHUctN+lUpYyMQy/dafHvUgug2YJ\n" \
65     "aRwN+QBL7GH6N75Mfh9t3dFTERxa1tphNeiVeqlb5/D2yY0JaqqIBUxpSsgpn/a1\n" \
66     "orR+XgAtMaHL0I+xwE1gdhYOWAhfcGo6vTD45b9fgERoeUC5KOUiZ2xABUV278lF\n" \
67     "QJ7uPwwhV+fjpwwZcum3viFnk5SUBtENhm9QGoH0KW8K43doPc7yeeaY4gxXdV1g\n" \
68     "im2uQ07Vk9bIm/HDYpW+tRQX7BM7o4BhqL7FbnKgfN2YcyMds+16YfugaaNJy53I\n" \
69     "O4640KT9NrpmJ0el+rmwb+2Ut9Ie+V7ja40V0M0hBToDWXjoIY2i9nf6rIXws76J\n" \
70     "A3jIMNTDLhoCT0cMcSs8zB9mqxNlbqkCAwEAAaNTMFEwHQYDVR0OBBYEFFPkZ81v\n" \
71     "G9lKvZv9XvKOOF0nwu8fMB8GA1UdIwQYMBaAFFPkZ81vG9lKvZv9XvKOOF0nwu8f\n" \
72     "MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBACjoiRIwP+mIggZ/\n" \
73     "PEBGqR+siV4TDDTVgUBeanLilkfKYeNEo4tapRy1Jvm2Kd/T26O2X2fTCVGG5Hpf\n" \
74     "KUYC9RLq7gPEytLUIlfwn0jp3uY3DotKQD03GWZ5nc0FJyhMoMH72MdoculbQ4UL\n" \
75     "x4CCrCvnGodXm0oXa6cEl4Do8MadU7fgRF1Bj05FD7LfDUgBGJp8pZbKiPIKLzAx\n" \
76     "UlMQen5PHJOke4+y2O/mL2iQshat7a5MOwJgPp1Wkn0q5kLO9AGVXbq3DD40jLrh\n" \
77     "b9EDVsWTa1Xu3RQV4zqHFsm3OGliwJbtO1BA6P7QFBRGMMos4xZQWjxJXbr1m+uf\n" \
78     "1y/X5icXdwWQ/f9h0ovjWeqOZBW8hfW6CRD1ehJpBB2YCwTjK7Fn5p4PH0PJUWf5\n" \
79     "rPuShvCAUy73QC/Iud4xwNQf6D9MWzOcDWvh7NPGhCHFmz4swKlN8oglMD1JaE4U\n" \
80     "97LLfATEYy5ajjlWoJ8qF/in8jzsYxq9OZ2/ObchZsU9ybzLRuE1Cv7v4Mx1sgH3\n" \
81     "EoWYZK1j3WytKmbaWYDR6INYklT/d+14OyIflUfBGiSXNKMITWVRZYjTHKUeAPdb\n" \
82     "1bsyMu+g4y1PVOrp/d9AyZTZrDW81zuYpO5Ah0DgF4EYiz2fWnz2ITVUmq35znIQ\n" \
83     "xg07nhvDeydwB48xXrPQ1KutrRyh\n"                                     \
84     "-----END CERTIFICATE-----"
85 
86 /* This function can be found in
87  * FreeRTOS/FreeRTOS-Plus/Source/FreeRTOS-Plus-PKCS11/3rdparty/mbedtls_utils/mbedtls_utils.c.
88  * It will be used to convert the RSA certificate from PEM format
89  * to DER format. */
90 extern int convert_pem_to_der( const unsigned char * pucInput,
91                                size_t xLen,
92                                unsigned char * pucOutput,
93                                size_t * pxOlen );
94 /*-----------------------------------------------------------*/
95 
96 
97 /**
98  * prvObjectImporting covers how to import a RSA certificate that was
99  * not generated by the Cryptoki library.
100  *
101  */
102 static void prvObjectImporting( void );
103 
104 /**
105  * prvObjectGeneration covers how to create a public key and private key pair
106  * with Cryptoki defined attributes using C_GenerateKeyPair.
107  *
108  * Note: The "sign-verify.c" demo has a dependency on the objects created
109  * in this function, and will not work without first running this function.
110  */
111 static void prvObjectGeneration( void );
112 
113 
114 /**
115  * This function details how to use the PKCS #11 "Object" functions to
116  * manage the objects abstracted by cryptoki.
117  *
118  * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.html
119  * please consult the standard for more information.
120  *
121  * The standard has grouped the functions presented in this demo as:
122  * Object Management Functions.
123  *
124  */
vPKCS11ObjectDemo(void)125 void vPKCS11ObjectDemo( void )
126 {
127     configPRINTF( ( "\r\nStarting PKCS #11 Objects Demo.\r\n" ) );
128 
129     /* PKCS #11 defines objects as "An item that is stored on a token. May be
130      * data, a certificate, or a key." This demo will show how to create objects
131      * that are managed by Cryptoki. */
132     prvObjectImporting();
133     prvObjectGeneration();
134     configPRINTF( ( "\r\nFinished PKCS #11 Objects Demo.\r\n" ) );
135 }
136 
prvObjectImporting(void)137 static void prvObjectImporting( void )
138 {
139     configPRINTF( ( "---------Importing Objects---------\r\n" ) );
140     configPRINTF( ( "Importing RSA Certificate...\r\n" ) );
141 
142     /* Helper variables and variables that have been covered. */
143     CK_RV xResult = CKR_OK;
144     CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
145     CK_SLOT_ID * pxSlotId = 0;
146     CK_FUNCTION_LIST_PTR pxFunctionList = NULL;
147     uint8_t * pucDerObject = NULL;
148     int32_t lConversionReturn = 0;
149     size_t xDerLen = 0;
150     CK_BBOOL xTokenStorage = CK_TRUE;
151     CK_OBJECT_HANDLE xCertHandle = CK_INVALID_HANDLE;
152     CK_BYTE xSubject[] = "TestSubject";
153 
154 
155     /* The PKCS11_CertificateTemplate_t is a custom struct defined in "core_pkcs11.h"
156      * in order to make it easier to import a certificate. This struct will be
157      * populated with the parameters necessary to import the certificate into the
158      * Cryptoki library.
159      */
160     PKCS11_CertificateTemplate_t xCertificateTemplate;
161 
162     /* The object class is specified as a certificate to help the Cryptoki library
163      * parse the arguments.
164      */
165     CK_OBJECT_CLASS xCertificateClass = CKO_CERTIFICATE;
166 
167     /* The certificate type is an x509 certificate, which is the only type
168      * supported by this stack. To read more about x509 certificates one can
169      * read the following:
170      *
171      * https://en.wikipedia.org/wiki/X.509
172      * https://www.ssl.com/faqs/what-is-an-x-509-certificate/
173      *
174      */
175     CK_CERTIFICATE_TYPE xCertificateType = CKC_X_509;
176 
177     /* The label will help the application identify which object it would like
178      * to access.
179      */
180     CK_BYTE pucLabel[] = pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS;
181 
182     /* Specify certificate class. */
183     xCertificateTemplate.xObjectClass.type = CKA_CLASS;
184     xCertificateTemplate.xObjectClass.pValue = &xCertificateClass;
185     xCertificateTemplate.xObjectClass.ulValueLen = sizeof( xCertificateClass );
186 
187     /* Specify certificate subject. */
188     xCertificateTemplate.xSubject.type = CKA_SUBJECT;
189     xCertificateTemplate.xSubject.pValue = xSubject;
190     xCertificateTemplate.xSubject.ulValueLen = sizeof( xSubject ) - 1UL;
191 
192     /* Point to contents of certificate. */
193     xCertificateTemplate.xValue.type = CKA_VALUE;
194     xCertificateTemplate.xValue.pValue = ( CK_VOID_PTR ) pkcs11demo_RSA_CERTIFICATE;
195     xCertificateTemplate.xValue.ulValueLen = ( CK_ULONG ) sizeof( pkcs11demo_RSA_CERTIFICATE ) - 1UL;
196 
197     /* Specify certificate label. */
198     xCertificateTemplate.xLabel.type = CKA_LABEL;
199     xCertificateTemplate.xLabel.pValue = ( CK_VOID_PTR ) pucLabel;
200     xCertificateTemplate.xLabel.ulValueLen = sizeof( pucLabel ) - 1UL;
201 
202     /* Specify certificate type as x509. */
203     xCertificateTemplate.xCertificateType.type = CKA_CERTIFICATE_TYPE;
204     xCertificateTemplate.xCertificateType.pValue = &xCertificateType;
205     xCertificateTemplate.xCertificateType.ulValueLen = sizeof( CK_CERTIFICATE_TYPE );
206 
207     /* Specify that the certificate should be on a token. */
208     xCertificateTemplate.xTokenObject.type = CKA_TOKEN;
209     xCertificateTemplate.xTokenObject.pValue = &xTokenStorage;
210     xCertificateTemplate.xTokenObject.ulValueLen = sizeof( xTokenStorage );
211 
212     vStart( &hSession, &pxSlotId );
213 
214     /* Ensure the Cryptoki library has the necessary functions implemented. */
215     xResult = C_GetFunctionList( &pxFunctionList );
216     configASSERT( xResult == CKR_OK );
217     configASSERT( pxFunctionList->C_CreateObject != NULL );
218 
219     /* Convert the certificate to DER format if it was in PEM. The DER key
220      * should be about 3/4 the size of the PEM key, so mallocing the PEM key
221      * size is sufficient. */
222     pucDerObject = pvPortMalloc( xCertificateTemplate.xValue.ulValueLen );
223     configASSERT( pucDerObject != NULL );
224 
225     xDerLen = xCertificateTemplate.xValue.ulValueLen;
226     lConversionReturn = convert_pem_to_der( xCertificateTemplate.xValue.pValue,
227                                             xCertificateTemplate.xValue.ulValueLen,
228                                             pucDerObject,
229                                             &xDerLen );
230 
231     configASSERT( 0 == lConversionReturn );
232 
233     /* Set the template pointers to refer to the DER converted objects. */
234     xCertificateTemplate.xValue.pValue = pucDerObject;
235     xCertificateTemplate.xValue.ulValueLen = xDerLen;
236 
237     /* Create an object using the encoded client certificate. */
238     configPRINTF( ( "Creating x509 certificate with label: %s \r\n",
239                     pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS ) );
240 
241     /* Once the Cryptoki library has finished importing the new x509 certificate
242      * a CK_OBJECT_HANDLE is associated with it. The application can now use this
243      * to refer to the object in following operations.
244      *
245      * xCertHandle in the below example will have it's value modified to
246      * be the CK_OBJECT_HANDLE.
247      *
248      * Compare the hard coded x509, in PEM format, with the DER formatted
249      * x509 certificate that is created by the Cryptoki library, with the following
250      * OpenSSL command:
251      * "$ openssl x509 -in corePKCS11_Certificate.dat -inform der -text"
252      *
253      * See this explanation for the difference between the PEM format and the
254      * DER format:
255      * https://stackoverflow.com/questions/22743415/what-are-the-differences-between-pem-cer-and-der/22743616
256      *
257      */
258     xResult = pxFunctionList->C_CreateObject( hSession,
259                                               ( CK_ATTRIBUTE_PTR ) &xCertificateTemplate,
260                                               sizeof( xCertificateTemplate ) / sizeof( CK_ATTRIBUTE ),
261                                               &xCertHandle );
262 
263     configASSERT( xResult == CKR_OK );
264     configASSERT( xCertHandle != CK_INVALID_HANDLE );
265 
266     configPRINTF( ( "corePKCS11_Certificate.dat has been created in the Visual Studio" \
267                     " Solution directory\r\n" ) );
268 
269     vPortFree( pucDerObject );
270     vEnd( hSession, pxSlotId );
271     configPRINTF( ( "Finished Importing RSA Certificate.\r\n" ) );
272     configPRINTF( ( "---------Finished Importing Objects---------\r\n" ) );
273 }
274 
prvObjectGeneration(void)275 static void prvObjectGeneration( void )
276 {
277     configPRINTF( ( "---------Generating Objects---------\r\n" ) );
278 
279     /* Helper variables. */
280     CK_RV xResult = CKR_OK;
281     CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
282     CK_SLOT_ID * pxSlotId = 0;
283     CK_FUNCTION_LIST_PTR pxFunctionList = NULL;
284     CK_BYTE * pxDerPublicKey = NULL;
285     CK_ULONG ulDerPublicKeyLength = 0;
286     CK_BBOOL xTrue = CK_TRUE;
287 
288     /* Specify the mechanism to use in the key pair generation. Mechanisms are
289      * previously explained in the "mechanims_and_digests.c" demo. */
290     CK_MECHANISM xMechanism =
291     {
292         CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0
293     };
294 
295     /* The EC curve used in this demo will be the named EC curve prime256v1.
296      * For further explanations of EC Cryptography please see the following:
297      * https://en.wikipedia.org/wiki/Elliptic-curve_cryptography
298      * https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography
299      */
300     CK_BYTE xEcParams[] = pkcs11DER_ENCODED_OID_P256;
301 
302     /* Specify the key type to be EC. */
303     CK_KEY_TYPE xKeyType = CKK_EC;
304 
305     /* Object handles are a token specific identifier for an object. They are
306      * used so the application's sessions can specify which object to interact
307      * with. Non-zero values are valid, 0 is always invalid, and is defined as
308      * CK_INVALID_HANDLE
309      *
310      * The lifetime of the handle is not necessarily the same as the lifetime of
311      * the object.
312      */
313     CK_OBJECT_HANDLE xPrivateKeyHandle = CK_INVALID_HANDLE;
314     CK_OBJECT_HANDLE xPublicKeyHandle = CK_INVALID_HANDLE;
315 
316 
317     /* Labels are application defined strings that are used to identify an
318      * object. It should not be NULL terminated. */
319     CK_BYTE pucPublicKeyLabel[] = { pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS };
320     CK_BYTE pucPrivateKeyLabel[] = { pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS };
321 
322     /* CK_ATTRIBUTE's contain an attribute type, a value, and the length of
323      * the value. An array of CK_ATTRIBUTEs is called a template. They are used
324      * for creating, searching, and manipulating for objects. The order of the
325      * template does not matter.
326      *
327      * In the below template we are creating a public key:
328      *      Specify the key type as EC.
329      *      The key will be able to verify a message.
330      *      Specify the EC Curve.
331      *      Assign a label to the object that will be created.
332      */
333     CK_ATTRIBUTE xPublicKeyTemplate[] =
334     {
335         { CKA_KEY_TYPE,  &xKeyType,         sizeof( xKeyType )              },
336         { CKA_VERIFY,    &xTrue,            sizeof( xTrue )                 },
337         { CKA_EC_PARAMS, xEcParams,         sizeof( xEcParams )             },
338         { CKA_LABEL,     pucPublicKeyLabel, sizeof( pucPublicKeyLabel ) - 1 }
339     };
340 
341     /* In the below template we are creating a private key:
342      *      The key type is EC.
343      *      The key is a token object.
344      *      The key will be a private key.
345      *      The key will be able to sign messages.
346      *      Assign a label to the object that will be created.
347      */
348     CK_ATTRIBUTE xPrivateKeyTemplate[] =
349     {
350         { CKA_KEY_TYPE, &xKeyType,          sizeof( xKeyType )               },
351         { CKA_TOKEN,    &xTrue,             sizeof( xTrue )                  },
352         { CKA_PRIVATE,  &xTrue,             sizeof( xTrue )                  },
353         { CKA_SIGN,     &xTrue,             sizeof( xTrue )                  },
354         { CKA_LABEL,    pucPrivateKeyLabel, sizeof( pucPrivateKeyLabel ) - 1 }
355     };
356 
357     vStart( &hSession, &pxSlotId );
358 
359     xResult = C_GetFunctionList( &pxFunctionList );
360     configASSERT( xResult == CKR_OK );
361 
362     configPRINTF( ( "Creating private key with label: %s \r\n",
363                     pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS ) );
364     configPRINTF( ( "Creating public key with label: %s \r\n",
365                     pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS ) );
366 
367     /* This function will generate a new EC private and public key pair. You can
368      * use " $openssl ec -inform der -in corePKCS11_Key.dat -text " to see
369      * the structure of the keys that were generated.
370      */
371     xResult = pxFunctionList->C_GenerateKeyPair( hSession,
372                                                  &xMechanism,
373                                                  xPublicKeyTemplate,
374                                                  sizeof( xPublicKeyTemplate ) / sizeof( CK_ATTRIBUTE ),
375                                                  xPrivateKeyTemplate,
376                                                  sizeof( xPrivateKeyTemplate ) / sizeof( CK_ATTRIBUTE ),
377                                                  &xPublicKeyHandle,
378                                                  &xPrivateKeyHandle );
379     configASSERT( xResult == CKR_OK );
380     configPRINTF( ( "corePKCS11_Key.dat has been created in the Visual Studio" \
381                     " Solution directory\r\n" ) );
382     configPRINTF( ( "Extracting public key bytes...\r\n" ) );
383 
384     /* Export public key as hex bytes and print the hex representation of the
385      * public key. */
386     vExportPublicKey( hSession,
387                       xPublicKeyHandle,
388                       &pxDerPublicKey,
389                       &ulDerPublicKeyLength );
390     vWriteHexBytesToConsole( "Public Key in Hex Format",
391                              pxDerPublicKey,
392                              ulDerPublicKeyLength );
393     configPRINTF( ( "---------Finished Generating Objects---------" ) );
394     vEnd( hSession, pxSlotId );
395 }
396