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