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