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