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 Crypto Component                                                 */
17 /**                                                                       */
18 /**  Transport Layer Security (TLS) - PKCS#1 v1.5 functions               */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #include "nx_crypto_pkcs1_v1.5.h"
24 
25 /* DER encodings (with OIDs for common algorithms) from RFC 8017.
26  * NOTE: This is the equivalent DER-encoding for the value "T" described in RFC 8017 section 9.2. */
27 static const UCHAR _NX_CRYPTO_DER_OID_SHA_1[]       =  {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
28 static const UCHAR _NX_CRYPTO_DER_OID_SHA_224[]     =  {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c};
29 static const UCHAR _NX_CRYPTO_DER_OID_SHA_256[]     =  {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
30 static const UCHAR _NX_CRYPTO_DER_OID_SHA_384[]     =  {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
31 static const UCHAR _NX_CRYPTO_DER_OID_SHA_512[]     =  {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
32 static const UCHAR _NX_CRYPTO_DER_OID_SHA_512_224[] =  {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05, 0x05, 0x00, 0x04, 0x1c};
33 static const UCHAR _NX_CRYPTO_DER_OID_SHA_512_256[] =  {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x06, 0x05, 0x00, 0x04, 0x20};
34 
35 
36 /**************************************************************************/
37 /*                                                                        */
38 /*  FUNCTION                                               RELEASE        */
39 /*                                                                        */
40 /*    _nx_crypto_pkcs1_v1_5_sign                          PORTABLE C      */
41 /*                                                           6.1          */
42 /*  AUTHOR                                                                */
43 /*                                                                        */
44 /*    Timothy Stapko, Microsoft Corporation                               */
45 /*                                                                        */
46 /*  DESCRIPTION                                                           */
47 /*                                                                        */
48 /*    This function generates an encoded signature using PKCS#1v1.5       */
49 /*    formatting.                                                         */
50 /*                                                                        */
51 /*  INPUT                                                                 */
52 /*                                                                        */
53 /*    input                                 Data to sign                  */
54 /*                                                                        */
55 /*  OUTPUT                                                                */
56 /*                                                                        */
57 /*    status                                Completion status             */
58 /*                                                                        */
59 /*  CALLS                                                                 */
60 /*                                                                        */
61 /*    [nx_crypto_operation]                 Crypto operations             */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
71 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
72 /*                                            resulting in version 6.1    */
73 /*                                                                        */
74 /**************************************************************************/
_nx_crypto_pkcs1_v1_5_sign(UCHAR * input,UINT input_length,UCHAR * private_key,UINT private_key_size,UCHAR * metadata_area,UCHAR * output,UINT output_size)75 NX_CRYPTO_KEEP UINT _nx_crypto_pkcs1_v1_5_sign(UCHAR *input, UINT input_length,
76                                                UCHAR *private_key, UINT private_key_size,
77                                                UCHAR *metadata_area,
78                                                UCHAR *output, UINT output_size)
79 {
80 NX_CRYPTO_PKCS1 *ctx = (NX_CRYPTO_PKCS1 *)metadata_area;
81 UINT status;
82 
83 /*  From RFC 8017 Section 9.2,  EMSA-PKCS1-v1_5-ENCODE (M, emLen):
84  *
85  *       1.  Apply the hash function to the message M to produce a hash
86  *        value H:
87  *
88  *           H = Hash(M).
89  *
90  *        If the hash function outputs "message too long", output
91  *        "message too long" and stop.
92  *
93  *    2.  Encode the algorithm ID for the hash function and the hash
94  *        value into an ASN.1 value of type DigestInfo (see
95  *        Appendix A.2.4) with the DER, where the type DigestInfo has
96  *        the syntax
97  *
98  *             DigestInfo ::= SEQUENCE {
99  *                 digestAlgorithm AlgorithmIdentifier,
100  *                 digest OCTET STRING
101  *             }
102  *
103  *        The first field identifies the hash function and the second
104  *        contains the hash value.  Let T be the DER encoding of the
105  *        DigestInfo value (see the notes below), and let tLen be the
106  *        length in octets of T.
107  *
108  *    3.  If emLen < tLen + 11, output "intended encoded message length
109  *        too short" and stop.
110  *
111  *    4.  Generate an octet string PS consisting of emLen - tLen - 3
112  *        octets with hexadecimal value 0xff.  The length of PS will be
113  *        at least 8 octets.
114  *
115  *    5.  Concatenate PS, the DER encoding T, and other padding to form
116  *        the encoded message EM as
117  *
118  *           EM = 0x00 || 0x01 || PS || 0x00 || T.
119  *
120  */
121 
122     /* Make sure we found a supported version (essentially an assertion check). */
123     if (ctx -> hash_method == NX_CRYPTO_NULL
124         || ctx -> public_cipher_method == NX_CRYPTO_NULL
125         || (ctx -> public_cipher_method) -> nx_crypto_init == NX_CRYPTO_NULL
126         || (ctx -> public_cipher_method) -> nx_crypto_operation == NX_CRYPTO_NULL)
127     {
128         return(NX_CRYPTO_PTR_ERROR);
129     }
130 
131     if (output_size < ctx -> modulus_size)
132     {
133         return(NX_CRYPTO_NOT_SUCCESSFUL);
134     }
135 
136     status = _nx_crypto_pkcs1_v1_5_encode(input, input_length, ctx -> hash_method, ctx -> hash_metadata, ctx -> hash_metadata_size, output, private_key_size);
137 
138     if(status != NX_CRYPTO_SUCCESS)
139     {
140         return(status);
141     }
142 
143     /* Initialize the crypto method with the modulus. */
144     status = (ctx -> public_cipher_method) -> nx_crypto_init(ctx -> public_cipher_method,
145                                                              ctx -> modulus,
146                                                              (NX_CRYPTO_KEY_SIZE)(ctx -> modulus_size << 3),
147                                                              NX_CRYPTO_NULL,
148                                                              ctx -> public_cipher_metadata,
149                                                              ctx -> public_cipher_metadata_size);
150     if (status)
151     {
152         return(status);
153     }
154 
155     /* Sign the hash we just generated using our local RSA private key (associated with our local cert). */
156     status = (ctx -> public_cipher_method) -> nx_crypto_operation(NX_CRYPTO_ENCRYPT,
157                                                                   NX_CRYPTO_NULL,
158                                                                   ctx -> public_cipher_method,
159                                                                   private_key,
160                                                                   (NX_CRYPTO_KEY_SIZE)(private_key_size << 3),
161                                                                   output,
162                                                                   (NX_CRYPTO_KEY_SIZE)(private_key_size),
163                                                                   NX_CRYPTO_NULL,
164                                                                   output,
165                                                                   output_size,
166                                                                   ctx -> public_cipher_metadata,
167                                                                   ctx -> public_cipher_metadata_size,
168                                                                   NX_CRYPTO_NULL, NX_CRYPTO_NULL);
169 
170     if(status != NX_CRYPTO_SUCCESS)
171     {
172         return(status);
173     }
174 
175     if ((ctx -> public_cipher_method) -> nx_crypto_cleanup)
176     {
177         status = (ctx -> public_cipher_method) -> nx_crypto_cleanup(ctx -> public_cipher_metadata);
178         if(status != NX_CRYPTO_SUCCESS)
179         {
180             return(status);
181         }
182     }
183 
184     return(NX_CRYPTO_SUCCESS);
185 }
186 
187 /**************************************************************************/
188 /*                                                                        */
189 /*  FUNCTION                                               RELEASE        */
190 /*                                                                        */
191 /*    _nx_crypto_pkcs1_v1_5_verify                        PORTABLE C      */
192 /*                                                           6.1.11       */
193 /*  AUTHOR                                                                */
194 /*                                                                        */
195 /*    Timothy Stapko, Microsoft Corporation                               */
196 /*                                                                        */
197 /*  DESCRIPTION                                                           */
198 /*                                                                        */
199 /*    This function verifies an encoded signature using PKCS#1v1.5        */
200 /*    formatting.                                                         */
201 /*                                                                        */
202 /*  INPUT                                                                 */
203 /*                                                                        */
204 /*    input                                 Data to sign                  */
205 /*                                                                        */
206 /*  OUTPUT                                                                */
207 /*                                                                        */
208 /*    status                                Completion status             */
209 /*                                                                        */
210 /*  CALLS                                                                 */
211 /*                                                                        */
212 /*    [nx_crypto_operation]                 Crypto operations             */
213 /*                                                                        */
214 /*  CALLED BY                                                             */
215 /*                                                                        */
216 /*                                                                        */
217 /*  RELEASE HISTORY                                                       */
218 /*                                                                        */
219 /*    DATE              NAME                      DESCRIPTION             */
220 /*                                                                        */
221 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
222 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
223 /*                                            resulting in version 6.1    */
224 /*  04-25-2022     Yuxin Zhou               Modified comment(s),          */
225 /*                                            corrected the operation,    */
226 /*                                            resulting in version 6.1.11 */
227 /*                                                                        */
228 /**************************************************************************/
_nx_crypto_pkcs1_v1_5_verify(UCHAR * message,UINT message_length,UCHAR * signature,UINT signature_length,UCHAR * public_key,UINT public_key_size,UCHAR * metadata_area)229 NX_CRYPTO_KEEP UINT _nx_crypto_pkcs1_v1_5_verify(UCHAR *message, UINT message_length,
230                                                  UCHAR *signature, UINT signature_length,
231                                                  UCHAR *public_key, UINT public_key_size,
232                                                  UCHAR *metadata_area)
233 {
234 UCHAR *EM1, *EM2;
235 NX_CRYPTO_PKCS1 *ctx = (NX_CRYPTO_PKCS1 *)metadata_area;
236 UINT status;
237 
238     /* Make sure we found a supported version (essentially an assertion check). */
239     if (ctx -> hash_method == NX_CRYPTO_NULL
240         || ctx -> public_cipher_method == NX_CRYPTO_NULL
241         || (ctx -> public_cipher_method) -> nx_crypto_init == NX_CRYPTO_NULL
242         || (ctx -> public_cipher_method) -> nx_crypto_operation == NX_CRYPTO_NULL)
243     {
244         return(NX_CRYPTO_PTR_ERROR);
245     }
246 
247     if (sizeof(ctx -> scratch_buffer) < (2 * (ctx -> modulus_size)))
248     {
249         return(NX_CRYPTO_NOT_SUCCESSFUL);
250     }
251 
252     /* Allocate space for encoded messages need to be compared. */
253     EM1 = ctx -> scratch_buffer;
254     EM2 = ctx -> scratch_buffer + ctx -> modulus_size;
255 
256     /* Initialize the crypto method with the modulus. */
257     status = (ctx -> public_cipher_method) -> nx_crypto_init(ctx -> public_cipher_method,
258                                                              ctx -> modulus,
259                                                              (NX_CRYPTO_KEY_SIZE)(ctx -> modulus_size << 3),
260                                                              NX_CRYPTO_NULL,
261                                                              ctx -> public_cipher_metadata,
262                                                              ctx -> public_cipher_metadata_size);
263     if (status)
264     {
265         return status;
266     }
267 
268     /* Decrypt the signature by the public key to get EM1 */
269     status = (ctx -> public_cipher_method) -> nx_crypto_operation(NX_CRYPTO_DECRYPT,
270                                                                   NX_CRYPTO_NULL,
271                                                                   ctx -> public_cipher_method,
272                                                                   public_key,
273                                                                   (NX_CRYPTO_KEY_SIZE)(public_key_size << 3),
274                                                                   signature,
275                                                                   signature_length,
276                                                                   NX_CRYPTO_NULL,
277                                                                   EM1,
278                                                                   ctx -> modulus_size,
279                                                                   ctx -> public_cipher_metadata,
280                                                                   ctx -> public_cipher_metadata_size,
281                                                                   NX_CRYPTO_NULL, NX_CRYPTO_NULL);
282     if (status)
283     {
284         return status;
285     }
286 
287     if ((ctx -> public_cipher_method) -> nx_crypto_cleanup)
288     {
289         status = (ctx -> public_cipher_method) -> nx_crypto_cleanup(ctx -> public_cipher_metadata);
290         if(status != NX_CRYPTO_SUCCESS)
291         {
292             return(status);
293         }
294     }
295 
296     /* Encoded the original message to get EM2. */
297     status = _nx_crypto_pkcs1_v1_5_encode(message, message_length, ctx -> hash_method, ctx -> hash_metadata, ctx -> hash_metadata_size, EM2, ctx -> modulus_size);
298     if(status != NX_CRYPTO_SUCCESS)
299     {
300         return(status);
301     }
302 
303     if (NX_CRYPTO_MEMCMP(EM1, EM2, ctx -> modulus_size))
304     {
305         return(NX_CRYPTO_NOT_SUCCESSFUL);
306     }
307 
308     return(NX_CRYPTO_SUCCESS);
309 }
310 
311 /**************************************************************************/
312 /*                                                                        */
313 /*  FUNCTION                                               RELEASE        */
314 /*                                                                        */
315 /*    _nx_crypto_pkcs1_v1_5_encode                        PORTABLE C      */
316 /*                                                           6.1          */
317 /*  AUTHOR                                                                */
318 /*                                                                        */
319 /*    Timothy Stapko, Microsoft Corporation                               */
320 /*                                                                        */
321 /*  DESCRIPTION                                                           */
322 /*                                                                        */
323 /*    This function encodes a message with PKCS#1v1.5.                    */
324 /*                                                                        */
325 /*  INPUT                                                                 */
326 /*                                                                        */
327 /*    input                                 Data to sign                  */
328 /*                                                                        */
329 /*  OUTPUT                                                                */
330 /*                                                                        */
331 /*    status                                Completion status             */
332 /*                                                                        */
333 /*  CALLS                                                                 */
334 /*                                                                        */
335 /*    [nx_crypto_operation]                 Crypto operations             */
336 /*                                                                        */
337 /*  CALLED BY                                                             */
338 /*                                                                        */
339 /*                                                                        */
340 /*  RELEASE HISTORY                                                       */
341 /*                                                                        */
342 /*    DATE              NAME                      DESCRIPTION             */
343 /*                                                                        */
344 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
345 /*  09-30-2020     Timothy Stapko           Modified comment(s), improved */
346 /*                                            buffer length verification, */
347 /*                                            verified memcpy use cases,  */
348 /*                                            resulting in version 6.1    */
349 /*                                                                        */
350 /**************************************************************************/
_nx_crypto_pkcs1_v1_5_encode(UCHAR * input,UINT input_length,NX_CRYPTO_METHOD * hash_method,UCHAR * metadata_area,UINT metadata_size,UCHAR * output,UINT expected_output_length)351 NX_CRYPTO_KEEP UINT _nx_crypto_pkcs1_v1_5_encode(UCHAR *input, UINT input_length,
352                                                  NX_CRYPTO_METHOD *hash_method,
353                                                  UCHAR *metadata_area, UINT metadata_size,
354                                                  UCHAR *output, UINT expected_output_length)
355 {
356 const UCHAR *der_encoding;
357 UINT der_encoding_length;
358 UINT signature_length = 0;
359 UINT hash_length;
360 UCHAR *working_ptr;
361 UINT status;
362 
363     /* PKCS-1 Signature padding. The scheme is to start with the block type (0x00, 0x01 for signing)
364        then pad with 0xFF bytes (for signing) followed with a single 0 byte right before the payload,
365        which comes at the end of the RSA block. */
366 
367     /* Start with a clear buffer. */
368     NX_CRYPTO_MEMSET(output, 0xff, expected_output_length);
369     output[0] = 0x0;
370     output[1] = 0x1;
371 
372     /* Get the size of the hash output. */
373     hash_length = (hash_method -> nx_crypto_ICV_size_in_bits) >> 3;
374 
375     /* Figure out which hash method we are using to get our DER-encoding. */
376     switch(hash_method -> nx_crypto_algorithm)
377     {
378     case NX_CRYPTO_HASH_SHA1:
379         der_encoding = _NX_CRYPTO_DER_OID_SHA_1;
380         der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_1);
381         break;
382     case NX_CRYPTO_HASH_SHA224:
383         der_encoding = _NX_CRYPTO_DER_OID_SHA_224;
384         der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_224);
385         break;
386     case NX_CRYPTO_HASH_SHA256:
387         der_encoding = _NX_CRYPTO_DER_OID_SHA_256;
388         der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_256);
389         break;
390     case NX_CRYPTO_HASH_SHA384:
391         der_encoding = _NX_CRYPTO_DER_OID_SHA_384;
392         der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_384);
393         break;
394     case NX_CRYPTO_HASH_SHA512:
395         der_encoding = _NX_CRYPTO_DER_OID_SHA_512;
396         der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_512);
397         break;
398     case NX_CRYPTO_HASH_SHA512_224:
399         der_encoding = _NX_CRYPTO_DER_OID_SHA_512_224;
400         der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_512_224);
401         break;
402     case NX_CRYPTO_HASH_SHA512_256:
403         der_encoding = _NX_CRYPTO_DER_OID_SHA_512_256;
404         der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_512_256);
405         break;
406     default:
407         return(NX_CRYPTO_AUTHENTICATION_FAILED);
408     }
409 
410     /* Encoded signature in RSA buffer (plaintext):
411      * signature_length = der_encoding_length + hash_length
412      * x = data_size - (der_encoding_length + hash_length)
413      * Length: |     x       |  der_encoding_length  | hash_length   |
414      * Field:  | Padding     |  DER encoding header  | Hash value    |
415      * Value:  | 0x0,0x1,... | <ASN.1 sequence, OID> | <hash output> |
416      */
417 
418     /* Calculate our final signature length for later offset calculations. */
419     signature_length = der_encoding_length + hash_length; /* DER encoding size + hash size = plaintext encoded signature length */
420     if (signature_length + 1 > expected_output_length)
421     {
422         return(NX_CRYPTO_SIZE_ERROR);
423     }
424     output[expected_output_length - signature_length - 1] = 0;
425 
426     /* Get a working pointer into the padded signature buffer. All PKCS-1 encoded data
427        comes at the end of the RSA encrypted block. */
428     working_ptr = &output[expected_output_length - signature_length];
429 
430     /* Copy in the DER encoding. */
431     NX_CRYPTO_MEMCPY(working_ptr, der_encoding, der_encoding_length); /* Use case of memcpy is verified. */
432 
433     /* Move the working pointer to the end of the DER encoding. */
434     working_ptr += der_encoding_length;
435 
436     /* Generate hash of input data using supplied hash method, placing it in the output buffer at the end
437      * of the RSA block (data_size).  */
438     status = hash_method -> nx_crypto_operation(NX_CRYPTO_AUTHENTICATE,
439                                        NX_CRYPTO_NULL,
440                                        hash_method,
441                                        NX_CRYPTO_NULL,
442                                        0,
443                                        input,
444                                        input_length,
445                                        NX_CRYPTO_NULL,
446                                        working_ptr,
447                                        hash_length,
448                                        metadata_area,
449                                        metadata_size,
450                                        NX_CRYPTO_NULL,
451                                        NX_CRYPTO_NULL);
452 
453     return (status);
454 }
455 
456 /**************************************************************************/
457 /*                                                                        */
458 /*  FUNCTION                                               RELEASE        */
459 /*                                                                        */
460 /*    _nx_crypto_method_pkcs1_v1_5_init                   PORTABLE C      */
461 /*                                                           6.3.0        */
462 /*  AUTHOR                                                                */
463 /*                                                                        */
464 /*    Timothy Stapko, Microsoft Corporation                               */
465 /*                                                                        */
466 /*  DESCRIPTION                                                           */
467 /*                                                                        */
468 /*    This function is the common crypto method init callback for         */
469 /*    Microsoft supported PKCS#1v1.5 cryptographic algorithm.             */
470 /*                                                                        */
471 /*  INPUT                                                                 */
472 /*                                                                        */
473 /*    method                                Pointer to crypto method      */
474 /*    key                                   Pointer to key                */
475 /*    key_size_in_bits                      Length of key size in bits    */
476 /*    handler                               Returned crypto handler       */
477 /*    crypto_metadata                       Metadata area                 */
478 /*    crypto_metadata_size                  Size of the metadata area     */
479 /*                                                                        */
480 /*  OUTPUT                                                                */
481 /*                                                                        */
482 /*    status                                Completion status             */
483 /*                                                                        */
484 /*  CALLS                                                                 */
485 /*                                                                        */
486 /*    None                                                                */
487 /*                                                                        */
488 /*  CALLED BY                                                             */
489 /*                                                                        */
490 /*    Application Code                                                    */
491 /*                                                                        */
492 /*  RELEASE HISTORY                                                       */
493 /*                                                                        */
494 /*    DATE              NAME                      DESCRIPTION             */
495 /*                                                                        */
496 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
497 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
498 /*                                            resulting in version 6.1    */
499 /*  10-31-2023     Yanwu Cai                Modified comment(s),          */
500 /*                                            resulting in version 6.3.0  */
501 /*                                                                        */
502 /**************************************************************************/
_nx_crypto_method_pkcs1_v1_5_init(struct NX_CRYPTO_METHOD_STRUCT * method,UCHAR * key,NX_CRYPTO_KEY_SIZE key_size_in_bits,VOID ** handle,VOID * crypto_metadata,ULONG crypto_metadata_size)503 NX_CRYPTO_KEEP UINT  _nx_crypto_method_pkcs1_v1_5_init(struct  NX_CRYPTO_METHOD_STRUCT *method,
504                                                        UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
505                                                        VOID  **handle,
506                                                        VOID  *crypto_metadata,
507                                                        ULONG crypto_metadata_size)
508 {
509 
510     NX_CRYPTO_PARAMETER_NOT_USED(key);
511     NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits);
512     NX_CRYPTO_PARAMETER_NOT_USED(handle);
513 
514     NX_CRYPTO_STATE_CHECK
515 
516     if ((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL))
517     {
518         return(NX_CRYPTO_PTR_ERROR);
519     }
520 
521     /* Verify the metadata address is 4-byte aligned. */
522     if((((ULONG)crypto_metadata) & 0x3) != 0)
523     {
524         return(NX_CRYPTO_PTR_ERROR);
525     }
526 
527     if(crypto_metadata_size < sizeof(NX_CRYPTO_PKCS1))
528     {
529         return(NX_CRYPTO_PTR_ERROR);
530     }
531 
532     return(NX_CRYPTO_SUCCESS);
533 }
534 
535 
536 /**************************************************************************/
537 /*                                                                        */
538 /*  FUNCTION                                               RELEASE        */
539 /*                                                                        */
540 /*    _nx_crypto_method_pkcs1_v1_5_cleanup                PORTABLE C      */
541 /*                                                           6.1          */
542 /*  AUTHOR                                                                */
543 /*                                                                        */
544 /*    Timothy Stapko, Microsoft Corporation                               */
545 /*                                                                        */
546 /*  DESCRIPTION                                                           */
547 /*                                                                        */
548 /*    This function cleans up the crypto metadata.                        */
549 /*                                                                        */
550 /*  INPUT                                                                 */
551 /*                                                                        */
552 /*    crypto_metadata                       Crypto metadata               */
553 /*                                                                        */
554 /*  OUTPUT                                                                */
555 /*                                                                        */
556 /*    status                                Completion status             */
557 /*                                                                        */
558 /*  CALLS                                                                 */
559 /*                                                                        */
560 /*    NX_CRYPTO_MEMSET                      Set the memory                */
561 /*                                                                        */
562 /*  CALLED BY                                                             */
563 /*                                                                        */
564 /*    Application Code                                                    */
565 /*                                                                        */
566 /*  RELEASE HISTORY                                                       */
567 /*                                                                        */
568 /*    DATE              NAME                      DESCRIPTION             */
569 /*                                                                        */
570 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
571 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
572 /*                                            resulting in version 6.1    */
573 /*                                                                        */
574 /**************************************************************************/
_nx_crypto_method_pkcs1_v1_5_cleanup(VOID * crypto_metadata)575 NX_CRYPTO_KEEP UINT  _nx_crypto_method_pkcs1_v1_5_cleanup(VOID *crypto_metadata)
576 {
577 
578     NX_CRYPTO_STATE_CHECK
579 
580 #ifdef NX_SECURE_KEY_CLEAR
581     if (!crypto_metadata)
582         return (NX_CRYPTO_SUCCESS);
583 
584     /* Clean up the crypto metadata.  */
585     NX_CRYPTO_MEMSET(crypto_metadata, 0, sizeof(NX_CRYPTO_PKCS1));
586 #else
587     NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata);
588 #endif/* NX_SECURE_KEY_CLEAR  */
589 
590     return(NX_CRYPTO_SUCCESS);
591 }
592 
593 /**************************************************************************/
594 /*                                                                        */
595 /*  FUNCTION                                               RELEASE        */
596 /*                                                                        */
597 /*    _nx_crypto_method_pkcs1_operation                   PORTABLE C      */
598 /*                                                           6.3.0        */
599 /*  AUTHOR                                                                */
600 /*                                                                        */
601 /*    Timothy Stapko, Microsoft Corporation                               */
602 /*                                                                        */
603 /*  DESCRIPTION                                                           */
604 /*                                                                        */
605 /*    This function performs an PKCS#1v1.5 operation.                     */
606 /*                                                                        */
607 /*  INPUT                                                                 */
608 /*                                                                        */
609 /*    op                                    PKCS#1v1.5 operation          */
610 /*    handle                                Crypto handle                 */
611 /*    method                                Cryption Method Object        */
612 /*    key                                   Encryption Key                */
613 /*    key_size_in_bits                      Key size in bits              */
614 /*    input                                 Input data                    */
615 /*    input_length_in_byte                  Input data size               */
616 /*    iv_ptr                                Initial vector                */
617 /*    output                                Output buffer                 */
618 /*    output_length_in_byte                 Output buffer size            */
619 /*    crypto_metadata                       Metadata area                 */
620 /*    crypto_metadata_size                  Metadata area size            */
621 /*    packet_ptr                            Pointer to packet             */
622 /*    nx_crypto_hw_process_callback         Callback function pointer     */
623 /*                                                                        */
624 /*  OUTPUT                                                                */
625 /*                                                                        */
626 /*    status                                Completion status             */
627 /*                                                                        */
628 /*  CALLS                                                                 */
629 /*                                                                        */
630 /*    _nx_crypto_pkcs1_v1_5_sign            Sign using PKCS#1v1.5         */
631 /*    _nx_crypto_pkcs1_v1_5_verify          Verify PKCS#1v1.5 signature   */
632 /*                                                                        */
633 /*  CALLED BY                                                             */
634 /*                                                                        */
635 /*    Application Code                                                    */
636 /*                                                                        */
637 /*  RELEASE HISTORY                                                       */
638 /*                                                                        */
639 /*    DATE              NAME                      DESCRIPTION             */
640 /*                                                                        */
641 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
642 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
643 /*                                            resulting in version 6.1    */
644 /*  10-31-2023     Yanwu Cai                Modified comment(s),          */
645 /*                                            resulting in version 6.3.0  */
646 /*                                                                        */
647 /**************************************************************************/
_nx_crypto_method_pkcs1_v1_5_operation(UINT op,VOID * handle,struct NX_CRYPTO_METHOD_STRUCT * method,UCHAR * key,NX_CRYPTO_KEY_SIZE key_size_in_bits,UCHAR * input,ULONG input_length_in_byte,UCHAR * iv_ptr,UCHAR * output,ULONG output_length_in_byte,VOID * crypto_metadata,ULONG crypto_metadata_size,VOID * packet_ptr,VOID (* nx_crypto_hw_process_callback)(VOID *,UINT))648 NX_CRYPTO_KEEP UINT _nx_crypto_method_pkcs1_v1_5_operation(UINT op,
649                                                            VOID *handle,
650                                                            struct NX_CRYPTO_METHOD_STRUCT *method,
651                                                            UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
652                                                            UCHAR *input, ULONG input_length_in_byte,
653                                                            UCHAR *iv_ptr,
654                                                            UCHAR *output, ULONG output_length_in_byte,
655                                                            VOID *crypto_metadata, ULONG crypto_metadata_size,
656                                                            VOID *packet_ptr,
657                                                            VOID (*nx_crypto_hw_process_callback)(VOID *, UINT))
658 {
659 NX_CRYPTO_PKCS1 *ctx;
660 NX_CRYPTO_PKCS1_OPTIONS *options;
661 UINT             status = NX_CRYPTO_SUCCESS;
662 
663     NX_CRYPTO_PARAMETER_NOT_USED(handle);
664     NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr);
665     NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr);
666     NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
667 
668     NX_CRYPTO_STATE_CHECK
669 
670     /* Verify the metadata address is 4-byte aligned. */
671     if((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL) || ((((ULONG)crypto_metadata) & 0x3) != 0))
672     {
673         return(NX_CRYPTO_PTR_ERROR);
674     }
675 
676     if(crypto_metadata_size < sizeof(NX_CRYPTO_PKCS1))
677     {
678         return(NX_CRYPTO_PTR_ERROR);
679     }
680 
681     ctx = (NX_CRYPTO_PKCS1 *)(crypto_metadata);
682 
683     if (op == NX_CRYPTO_SET_ADDITIONAL_DATA)
684     {
685         options = (NX_CRYPTO_PKCS1_OPTIONS *)input;
686 
687         if ((options -> public_cipher_metadata_size < (options -> public_cipher_method) -> nx_crypto_metadata_area_size)
688             || (options -> hash_metadata_size < (options -> hash_method) -> nx_crypto_metadata_area_size))
689         {
690             return(NX_CRYPTO_NOT_SUCCESSFUL);
691         }
692 
693         ctx -> public_cipher_method = options -> public_cipher_method;
694         ctx -> public_cipher_metadata = options -> public_cipher_metadata;
695         ctx -> public_cipher_metadata_size = options -> public_cipher_metadata_size;
696         ctx -> hash_method = options -> hash_method;
697         ctx -> hash_metadata = options -> hash_metadata;
698         ctx -> hash_metadata_size = options -> hash_metadata_size;
699         ctx -> modulus = key;
700         ctx -> modulus_size = (key_size_in_bits >> 3);
701     }
702     else if (op == NX_CRYPTO_AUTHENTICATE)
703     {
704         status = _nx_crypto_pkcs1_v1_5_sign(input,
705                                             input_length_in_byte,
706                                             key,
707                                             (key_size_in_bits >> 3),
708                                             crypto_metadata,
709                                             output,
710                                             output_length_in_byte);
711 
712     }
713     else if (op == NX_CRYPTO_VERIFY)
714     {
715         status = _nx_crypto_pkcs1_v1_5_verify(input,
716                                               input_length_in_byte,
717                                               output,
718                                               output_length_in_byte,
719                                               key,
720                                               (key_size_in_bits >> 3),
721                                               crypto_metadata);
722     }
723     else
724     {
725         status = NX_CRYPTO_NOT_SUCCESSFUL;
726     }
727 
728     return(status);
729 }
730