Contiki-NG
Loading...
Searching...
No Matches
bignum-driver.c
Go to the documentation of this file.
1/*
2 * Original file:
3 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
4 * All rights reserved.
5 *
6 * Port to Contiki:
7 * Authors: Andreas Dröscher <contiki@anticat.ch>
8 * Hu Luo
9 * Hossein Shafagh <shafagh@inf.ethz.ch>
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of the copyright holder nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37/**
38 * \addtogroup cc2538-bignum
39 * @{
40 *
41 * \file
42 * Implementation of the cc2538 BigNum driver
43 *
44 * bignum_subtract_start bignum_subtract_get_result (subtraction)
45 * bignum_add_start bignum_add_get_result (addition)
46 * bignum_mod_start bignum_mod_get_result (modulo)
47 * bignum_exp_mod_start bignum_exp_mod_get_result (modular exponentiation operation)
48 * bignum_inv_mod_start bignum_inv_mod_get_result (inverse modulo operation)
49 * bignum_mul_start bignum_mul_get_result (multiplication)
50 * bignum_divide_start bignum_divide_get_result (division)
51 * bignum_cmp_start bignum_cmp_get_result (comparison)
52 */
53#include "dev/bignum-driver.h"
54
55#include <stdio.h>
56
57#include "reg.h"
58#include "dev/nvic.h"
59
60#define ASSERT(IF) if(!(IF)) { return PKA_STATUS_INVALID_PARAM; }
61
62/*---------------------------------------------------------------------------*/
63uint8_t
64bignum_mod_start(const uint32_t *number,
65 const uint8_t number_size,
66 const uint32_t *modulus,
67 const uint8_t modulus_size,
68 uint32_t *result_vector,
69 struct process *process)
70{
71
72 uint8_t extraBuf;
73 uint32_t offset;
74 int i;
75
76 /* Check the arguments. */
77 ASSERT(NULL != number);
78 ASSERT(NULL != modulus);
79 ASSERT(NULL != result_vector);
80
81 /* make sure no operation is in progress. */
82 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
84 }
85
86 /* calculate the extra buffer requirement. */
87 extraBuf = 2 + modulus_size % 2;
88
89 offset = 0;
90
91 /* Update the A ptr with the offset address of the PKA RAM location
92 * where the number will be stored. */
93 REG(PKA_APTR) = offset >> 2;
94
95 /* Load the number in PKA RAM */
96 for(i = 0; i < number_size; i++) {
97 REG(PKA_RAM_BASE + offset + 4 * i) = number[i];
98 }
99
100 /* determine the offset for the next data input. */
101 offset += 4 * (i + number_size % 2);
102
103 /* Update the B ptr with the offset address of the PKA RAM location
104 * where the divisor will be stored. */
105 REG(PKA_BPTR) = offset >> 2;
106
107 /* Load the divisor in PKA RAM. */
108 for(i = 0; i < modulus_size; i++) {
109 REG(PKA_RAM_BASE + offset + 4 * i) = modulus[i];
110 }
111
112 /* determine the offset for the next data. */
113 offset += 4 * (i + extraBuf);
114
115 /* Copy the result vector address location. */
116 *result_vector = PKA_RAM_BASE + offset;
117
118 /* Load C ptr with the result location in PKA RAM */
119 REG(PKA_CPTR) = offset >> 2;
120
121 /* Load A length registers with Big number length in 32 bit words. */
122 REG(PKA_ALENGTH) = number_size;
123
124 /* Load B length registers Divisor length in 32-bit words. */
125 REG(PKA_BLENGTH) = modulus_size;
126
127 /* Start the PKCP modulo operation by setting the PKA Function register. */
129
130 /* Enable Interrupt */
131 if(process != NULL) {
133 NVIC_ClearPendingIRQ(PKA_IRQn);
134 NVIC_EnableIRQ(PKA_IRQn);
135 }
136
137 return PKA_STATUS_SUCCESS;
138}
139/*---------------------------------------------------------------------------*/
140uint8_t
141bignum_mod_get_result(uint32_t *buffer,
142 const uint8_t buffer_size,
143 const uint32_t result_vector)
144{
145
146 uint32_t regMSWVal;
147 uint32_t len;
148 int i;
149
150 /* Check the arguments. */
151 ASSERT(NULL != buffer);
152 ASSERT(result_vector > PKA_RAM_BASE);
153 ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
154
155 /* verify that the operation is complete. */
156 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
158 }
159
160 /* Disable Interrupt */
161 NVIC_DisableIRQ(PKA_IRQn);
163
164 /* Get the MSW register value. */
165 regMSWVal = REG(PKA_DIVMSW);
166
167 /* Check to make sure that the result vector is not all zeroes. */
168 if(regMSWVal & PKA_DIVMSW_RESULT_IS_ZERO) {
169 return PKA_STATUS_RESULT_0;
170 }
171
172 /* Get the length of the result. */
173 len = ((regMSWVal & PKA_DIVMSW_MSW_ADDRESS_M) + 1)
174 - ((result_vector - PKA_RAM_BASE) >> 2);
175
176 /* If the size of the buffer provided is less than the result length than
177 * return error. */
178 if(buffer_size < len) {
180 }
181 /* copy the result from vector C into the pResult. */
182 for(i = 0; i < len; i++) {
183 buffer[i] = REG(result_vector + 4 * i);
184 }
185
186 return PKA_STATUS_SUCCESS;
187}
188/*---------------------------------------------------------------------------*/
189uint8_t
190bignum_cmp_start(const uint32_t *number1,
191 const uint32_t *number2,
192 const uint8_t size,
193 struct process *process)
194{
195
196 uint32_t offset;
197 int i;
198
199 /* Check the arguments. */
200 ASSERT(NULL != number1);
201 ASSERT(NULL != number2);
202
203 offset = 0;
204
205 /* Make sure no operation is in progress. */
206 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
208 }
209
210 /* Update the A ptr with the offset address of the PKA RAM location
211 * where the first big number will be stored. */
212 REG(PKA_APTR) = offset >> 2;
213
214 /* Load the first big number in PKA RAM. */
215 for(i = 0; i < size; i++) {
216 REG(PKA_RAM_BASE + offset + 4 * i) = number1[i];
217 }
218
219 /* Determine the offset in PKA RAM for the next pointer. */
220 offset += 4 * (i + size % 2);
221
222 /* Update the B ptr with the offset address of the PKA RAM location
223 * where the second big number will be stored. */
224 REG(PKA_BPTR) = offset >> 2;
225
226 /* Load the second big number in PKA RAM. */
227 for(i = 0; i < size; i++) {
228 REG(PKA_RAM_BASE + offset + 4 * i) = number2[i];
229 }
230
231 /* Load length registers in 32 bit word size. */
232 REG(PKA_ALENGTH) = size;
233
234 /* Set the PKA Function register for the compare operation
235 * and start the operation. */
237
238 /* Enable Interrupt */
239 if(process != NULL) {
241 NVIC_ClearPendingIRQ(PKA_IRQn);
242 NVIC_EnableIRQ(PKA_IRQn);
243 }
244
245 return PKA_STATUS_SUCCESS;
246}
247/*---------------------------------------------------------------------------*/
248uint8_t
250{
251 uint8_t status;
252
253 /* verify that the operation is complete. */
254 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
256 return status;
257 }
258
259 /* Disable Interrupt */
260 NVIC_DisableIRQ(PKA_IRQn);
262
263 /* Check the compare register. */
264 switch(REG(PKA_COMPARE)) {
266 status = PKA_STATUS_SUCCESS;
267 break;
268
270 status = PKA_STATUS_A_GR_B;
271 break;
272
274 status = PKA_STATUS_A_LT_B;
275 break;
276
277 default:
278 status = PKA_STATUS_FAILURE;
279 break;
280 }
281
282 return status;
283}
284/*---------------------------------------------------------------------------*/
285uint8_t
286bignum_inv_mod_start(const uint32_t *number,
287 const uint8_t number_size,
288 const uint32_t *modulus,
289 const uint8_t modulus_size,
290 uint32_t *result_vector,
291 struct process *process)
292{
293
294 uint32_t offset;
295 int i;
296
297 /* Check the arguments. */
298 ASSERT(NULL != number);
299 ASSERT(NULL != modulus);
300 ASSERT(NULL != result_vector);
301
302 offset = 0;
303
304 /* Make sure no operation is in progress. */
305 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
307 }
308
309 /* Update the A ptr with the offset address of the PKA RAM location
310 * where the number will be stored. */
311 REG(PKA_APTR) = offset >> 2;
312
313 /* Load the \e number number in PKA RAM. */
314 for(i = 0; i < number_size; i++) {
315 REG(PKA_RAM_BASE + offset + 4 * i) = number[i];
316 }
317
318 /* Determine the offset for next data. */
319 offset += 4 * (i + number_size % 2);
320
321 /* Update the B ptr with the offset address of the PKA RAM location
322 * where the modulus will be stored. */
323 REG(PKA_BPTR) = offset >> 2;
324
325 /* Load the \e modulus divisor in PKA RAM. */
326 for(i = 0; i < modulus_size; i++) {
327 REG(PKA_RAM_BASE + offset + 4 * i) = modulus[i];
328 }
329
330 /* Determine the offset for result data. */
331 offset += 4 * (i + modulus_size % 2);
332
333 /* Copy the result vector address location. */
334 *result_vector = PKA_RAM_BASE + offset;
335
336 /* Load D ptr with the result location in PKA RAM. */
337 REG(PKA_DPTR) = offset >> 2;
338
339 /* Load the respective length registers. */
340 REG(PKA_ALENGTH) = number_size;
341 REG(PKA_BLENGTH) = modulus_size;
342
343 /* set the PKA function to InvMod operation and the start the operation. */
344 REG(PKA_FUNCTION) = 0x0000F000;
345
346 /* Enable Interrupt */
347 if(process != NULL) {
349 NVIC_ClearPendingIRQ(PKA_IRQn);
350 NVIC_EnableIRQ(PKA_IRQn);
351 }
352
353 return PKA_STATUS_SUCCESS;
354}
355/*---------------------------------------------------------------------------*/
356uint8_t
358 const uint8_t buffer_size,
359 const uint32_t result_vector)
360{
361
362 uint32_t regMSWVal;
363 uint32_t len;
364 int i;
365
366 /* Check the arguments. */
367 ASSERT(NULL != buffer);
368 ASSERT(result_vector > PKA_RAM_BASE);
369 ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
370
371 /* Verify that the operation is complete. */
372 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
374 }
375
376 /* Disable Interrupt */
377 NVIC_DisableIRQ(PKA_IRQn);
379
380 /* Get the MSW register value. */
381 regMSWVal = REG(PKA_MSW);
382
383 /* Check to make sure that the result vector is not all zeroes. */
384 if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
385 return PKA_STATUS_RESULT_0;
386 }
387
388 /* Get the length of the result */
389 len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
390 - ((result_vector - PKA_RAM_BASE) >> 2);
391
392 /* Check if the provided buffer length is adequate to store the result
393 * data. */
394 if(buffer_size < len) {
396 }
397
398 /* Copy the result from vector C into the \e buffer. */
399 for(i = 0; i < len; i++) {
400 buffer[i] = REG(result_vector + 4 * i);
401 }
402
403 return PKA_STATUS_SUCCESS;
404}
405/*---------------------------------------------------------------------------*/
406uint8_t
407bignum_mul_start(const uint32_t *multiplicand,
408 const uint8_t multiplicand_size,
409 const uint32_t *multiplier,
410 const uint8_t multiplier_size,
411 uint32_t *result_vector,
412 struct process *process)
413{
414
415 uint32_t offset;
416 int i;
417
418 /* Check for the arguments. */
419 ASSERT(NULL != multiplicand);
420 ASSERT(NULL != multiplier);
421 ASSERT(NULL != result_vector);
422
423 offset = 0;
424
425 /* Make sure no operation is in progress. */
426 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
428 }
429
430 /* Update the A ptr with the offset address of the PKA RAM location
431 * where the multiplicand will be stored. */
432 REG(PKA_APTR) = offset >> 2;
433
434 /* Load the multiplicand in PKA RAM. */
435 for(i = 0; i < multiplicand_size; i++) {
436 REG(PKA_RAM_BASE + offset + 4 * i) = *multiplicand;
437 multiplicand++;
438 }
439
440 /* Determine the offset for the next data. */
441 offset += 4 * (i + (multiplicand_size % 2));
442
443 /* Update the B ptr with the offset address of the PKA RAM location
444 * where the multiplier will be stored. */
445 REG(PKA_BPTR) = offset >> 2;
446
447 /* Load the multiplier in PKA RAM. */
448 for(i = 0; i < multiplier_size; i++) {
449 REG(PKA_RAM_BASE + offset + 4 * i) = *multiplier;
450 multiplier++;
451 }
452
453 /* Determine the offset for the next data. */
454 offset += 4 * (i + (multiplier_size % 2));
455
456 /* Copy the result vector address location. */
457 *result_vector = PKA_RAM_BASE + offset;
458
459 /* Load C ptr with the result location in PKA RAM. */
460 REG(PKA_CPTR) = offset >> 2;
461
462 /* Load the respective length registers. */
463 REG(PKA_ALENGTH) = multiplicand_size;
464 REG(PKA_BLENGTH) = multiplier_size;
465
466 /* Set the PKA function to the multiplication and start it. */
468
469 /* Enable Interrupt */
470 if(process != NULL) {
472 NVIC_ClearPendingIRQ(PKA_IRQn);
473 NVIC_EnableIRQ(PKA_IRQn);
474 }
475
476 return PKA_STATUS_SUCCESS;
477}
478/*---------------------------------------------------------------------------*/
479uint8_t
480bignum_mul_get_result(uint32_t *buffer,
481 uint32_t *buffer_size,
482 const uint32_t result_vector)
483{
484
485 uint32_t regMSWVal;
486 uint32_t len;
487 int i;
488
489 /* Check for arguments. */
490 ASSERT(NULL != buffer);
491 ASSERT(NULL != buffer_size);
492 ASSERT(result_vector > PKA_RAM_BASE);
493 ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
494
495 /* Verify that the operation is complete. */
496 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
498 }
499
500 /* Disable Interrupt */
501 NVIC_DisableIRQ(PKA_IRQn);
503
504 /* Get the MSW register value. */
505 regMSWVal = REG(PKA_MSW);
506
507 /* Check to make sure that the result vector is not all zeroes. */
508 if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
509 return PKA_STATUS_RESULT_0;
510 }
511
512 /* Get the length of the result. */
513 len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
514 - ((result_vector - PKA_RAM_BASE) >> 2);
515
516 /* Make sure that the length of the supplied result buffer is adequate
517 * to store the resultant. */
518 if(*buffer_size < len) {
520 }
521
522 /* Copy the resultant length. */
523 *buffer_size = len;
524
525 /* Copy the result from vector C into the pResult. */
526 for(i = 0; i < *buffer_size; i++) {
527 buffer[i] = REG(result_vector + 4 * i);
528 }
529
530 return PKA_STATUS_SUCCESS;
531}
532/*---------------------------------------------------------------------------*/
533uint8_t
534bignum_add_start(const uint32_t *number1,
535 const uint8_t number1_size,
536 const uint32_t *number2,
537 const uint8_t number2_size,
538 uint32_t *result_vector,
539 struct process *process)
540{
541
542 uint32_t offset;
543 int i;
544
545 /* Check for arguments. */
546 ASSERT(NULL != number1);
547 ASSERT(NULL != number2);
548 ASSERT(NULL != result_vector);
549
550 offset = 0;
551
552 /* Make sure no operation is in progress. */
553 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
555 }
556
557 /* Update the A ptr with the offset address of the PKA RAM location
558 * where the big number 1 will be stored. */
559 REG(PKA_APTR) = offset >> 2;
560
561 /* Load the big number 1 in PKA RAM. */
562 for(i = 0; i < number1_size; i++) {
563 REG(PKA_RAM_BASE + offset + 4 * i) = number1[i];
564 }
565
566 /* Determine the offset in PKA RAM for the next data. */
567 offset += 4 * (i + (number1_size % 2));
568
569 /* Update the B ptr with the offset address of the PKA RAM location
570 * where the big number 2 will be stored. */
571 REG(PKA_BPTR) = offset >> 2;
572
573 /* Load the big number 2 in PKA RAM. */
574 for(i = 0; i < number2_size; i++) {
575 REG(PKA_RAM_BASE + offset + 4 * i) = number2[i];
576 }
577
578 /* Determine the offset in PKA RAM for the next data. */
579 offset += 4 * (i + (number2_size % 2));
580
581 /* Copy the result vector address location. */
582 *result_vector = PKA_RAM_BASE + offset;
583
584 /* Load C ptr with the result location in PKA RAM. */
585 REG(PKA_CPTR) = offset >> 2;
586
587 /* Load respective length registers. */
588 REG(PKA_ALENGTH) = number1_size;
589 REG(PKA_BLENGTH) = number2_size;
590
591 /* Set the function for the add operation and start the operation. */
593
594 /* Enable Interrupt */
595 if(process != NULL) {
597 NVIC_ClearPendingIRQ(PKA_IRQn);
598 NVIC_EnableIRQ(PKA_IRQn);
599 }
600
601 return PKA_STATUS_SUCCESS;
602}
603/*---------------------------------------------------------------------------*/
604uint8_t
605bignum_add_get_result(uint32_t *buffer,
606 uint32_t *buffer_size,
607 const uint32_t result_vector)
608{
609
610 uint32_t regMSWVal;
611 uint32_t len;
612 int i;
613
614 /* Check for the arguments. */
615 ASSERT(NULL != buffer);
616 ASSERT(NULL != buffer_size);
617 ASSERT(result_vector > PKA_RAM_BASE);
618 ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
619
620 /* Verify that the operation is complete. */
621 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
623 }
624
625 /* Disable Interrupt */
626 NVIC_DisableIRQ(PKA_IRQn);
628
629 /* Get the MSW register value. */
630 regMSWVal = REG(PKA_MSW);
631
632 /* Check to make sure that the result vector is not all zeroes. */
633 if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
634 return PKA_STATUS_RESULT_0;
635 }
636
637 /* Get the length of the result. */
638 len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
639 - ((result_vector - PKA_RAM_BASE) >> 2);
640
641 /* Make sure that the supplied result buffer is adequate to store the
642 * resultant data. */
643 if(*buffer_size < len) {
645 }
646
647 /* Copy the length. */
648 *buffer_size = len;
649
650 /* Copy the result from vector C into the provided buffer. */
651 for(i = 0; i < *buffer_size; i++) {
652 buffer[i] = REG(result_vector + 4 * i);
653 }
654
655 return PKA_STATUS_SUCCESS;
656}
657/*---------------------------------------------------------------------------*/
658/* below functions are added by hu luo */
659uint8_t
660bignum_subtract_start(const uint32_t *number1,
661 const uint8_t number1_size,
662 const uint32_t *number2,
663 const uint8_t number2_size,
664 uint32_t *result_vector,
665 struct process *process)
666{
667
668 uint32_t offset;
669 int i;
670
671 /* Check for arguments. */
672 ASSERT(NULL != number1);
673 ASSERT(NULL != number2);
674 ASSERT(NULL != result_vector);
675
676 offset = 0;
677
678 /* Make sure no operation is in progress. */
679 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
681 }
682
683 /* Update the A ptr with the offset address of the PKA RAM location
684 * where the big number 1 will be stored. */
685 REG(PKA_APTR) = offset >> 2;
686
687 /* Load the big number 1 in PKA RAM. */
688 for(i = 0; i < number1_size; i++) {
689 REG(PKA_RAM_BASE + offset + 4 * i) = number1[i];
690 }
691
692 /* Determine the offset in PKA RAM for the next data. */
693 offset += 4 * (i + (number1_size % 2));
694
695 /* Update the B ptr with the offset address of the PKA RAM location
696 * where the big number 2 will be stored. */
697 REG(PKA_BPTR) = offset >> 2;
698
699 /* Load the big number 2 in PKA RAM. */
700 for(i = 0; i < number2_size; i++) {
701 REG(PKA_RAM_BASE + offset + 4 * i) = number2[i];
702 }
703
704 /* Determine the offset in PKA RAM for the next data. */
705 offset += 4 * (i + (number2_size % 2));
706
707 /* Copy the result vector address location. */
708 *result_vector = PKA_RAM_BASE + offset;
709
710 /* Load C ptr with the result location in PKA RAM. */
711 REG(PKA_CPTR) = offset >> 2;
712
713 /* Load respective length registers. */
714 REG(PKA_ALENGTH) = number1_size;
715 REG(PKA_BLENGTH) = number2_size;
716
717 /* Set the function for the add operation and start the operation. */
719
720 /* Enable Interrupt */
721 if(process != NULL) {
723 NVIC_ClearPendingIRQ(PKA_IRQn);
724 NVIC_EnableIRQ(PKA_IRQn);
725 }
726
727 return PKA_STATUS_SUCCESS;
728}
729/*---------------------------------------------------------------------------*/
730uint8_t
732 uint32_t *buffer_size,
733 const uint32_t result_vector)
734{
735
736 uint32_t regMSWVal;
737 uint32_t len;
738 int i;
739
740 /* Check for the arguments. */
741 ASSERT(NULL != buffer);
742 ASSERT(NULL != buffer_size);
743 ASSERT(result_vector > PKA_RAM_BASE);
744 ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
745
746 /* Verify that the operation is complete. */
747 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
749 }
750
751 /* Disable Interrupt */
752 NVIC_DisableIRQ(PKA_IRQn);
754
755 /* Get the MSW register value. */
756 regMSWVal = REG(PKA_MSW);
757
758 /* Check to make sure that the result vector is not all zeroes. */
759 if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
760 return PKA_STATUS_RESULT_0;
761 }
762
763 /* Get the length of the result. */
764 len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
765 - ((result_vector - PKA_RAM_BASE) >> 2);
766
767 /* Make sure that the supplied result buffer is adequate to store the
768 * resultant data. */
769 if(*buffer_size < len) {
771 }
772
773 /* Copy the length. */
774 *buffer_size = len;
775
776 /* Copy the result from vector C into the provided buffer. */
777 for(i = 0; i < *buffer_size; i++) {
778 buffer[i] = REG(result_vector + 4 * i);
779 }
780
781 return PKA_STATUS_SUCCESS;
782}
783/*---------------------------------------------------------------------------*/
784uint8_t
785bignum_exp_mod_start(const uint32_t *number,
786 const uint8_t number_size,
787 const uint32_t *modulus,
788 const uint8_t modulus_size,
789 const uint32_t *base,
790 const uint8_t base_size,
791 uint32_t *result_vector,
792 struct process *process)
793{
794 uint32_t offset;
795 int i;
796
797 /* Check for the arguments. */
798 ASSERT(NULL != number);
799 ASSERT(NULL != modulus);
800 ASSERT(NULL != base);
801 ASSERT(NULL != result_vector);
802 ASSERT(modulus != base);
803
804 offset = 0;
805
806 /* Make sure no PKA operation is in progress. */
807 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
809 }
810
811 /* Update the A ptr with the offset address of the PKA RAM location
812 * where the exponent will be stored. */
813 REG(PKA_APTR) = offset >> 2;
814
815 /* Load the Exponent in PKA RAM. */
816 for(i = 0; i < number_size; i++) {
817 REG(PKA_RAM_BASE + offset + 4 * i) = number[i];
818 }
819
820 /* Determine the offset for the next data(BPTR). */
821 offset += 4 * (i + number_size % 2);
822 /* Update the B ptr with the offset address of the PKA RAM location
823 * where the divisor will be stored. */
824 REG(PKA_BPTR) = offset >> 2;
825
826 /* Load the Modulus in PKA RAM. */
827 for(i = 0; i < modulus_size; i++) {
828 REG(PKA_RAM_BASE + offset + 4 * i) = modulus[i];
829 }
830
831 /* Determine the offset for the next data(CPTR). */
832 offset += 4 * (i + modulus_size % 2 + 2);
833 /* Update the C ptr with the offset address of the PKA RAM location
834 * where the Base will be stored. */
835 REG(PKA_CPTR) = offset >> 2;
836
837 /* Write Base to the Vector C in PKA RAM */
838
839 for(i = 0; i < base_size; i++) {
840 REG(PKA_RAM_BASE + offset + 4 * i) = base[i];
841 }
842
843 /* Determine the offset for the next data.
844 * INFO D and B can share the same memory area!
845 * offset += 4 * (i + extraBuf + 2); */
846
847 /* Copy the result vector address location. */
848 *result_vector = PKA_RAM_BASE + offset;
849
850 /* Load D ptr with the result location in PKA RAM */
851 REG(PKA_DPTR) = offset >> 2;
852
853 /* Load A length registers with Big number length in 32 bit words. */
854 REG(PKA_ALENGTH) = number_size;
855
856 /* Load B length registers Divisor length in 32-bit words. */
857 REG(PKA_BLENGTH) = modulus_size;
858 /* REG(PKA_SHIFT) = 0x00000001;
859 * Required for (EXPMod-variable): 0x0000A000
860 * Start the PKCP modulo exponentiation operation(EXPMod-ACT2)
861 * by setting the PKA Function register. */
862 REG(PKA_FUNCTION) = 0x0000C000;
863
864 /* Enable Interrupt */
865 if(process != NULL) {
867 NVIC_ClearPendingIRQ(PKA_IRQn);
868 NVIC_EnableIRQ(PKA_IRQn);
869 }
870
871 return PKA_STATUS_SUCCESS;
872}
873/*---------------------------------------------------------------------------*/
874uint8_t
876 const uint8_t buffer_size,
877 const uint32_t result_vector)
878{
879
880 uint32_t regMSWVal;
881 uint32_t len;
882 int i;
883
884 /* Check the arguments. */
885 ASSERT(NULL != buffer);
886 ASSERT(result_vector > PKA_RAM_BASE);
887 ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
888
889 /* verify that the operation is complete. */
890 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
892 }
893
894 /* Disable Interrupt */
895 NVIC_DisableIRQ(PKA_IRQn);
897
898 /* Get the MSW register value. */
899 regMSWVal = REG(PKA_MSW);
900
901 /* Check to make sure that the result vector is not all zeroes. */
902 if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
903 return PKA_STATUS_RESULT_0;
904 }
905
906 /* Get the length of the result */
907 len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
908 - ((result_vector - PKA_RAM_BASE) >> 2);
909 /* If the size of the buffer provided is less than the result length than
910 * return error. */
911 if(buffer_size < len) {
913 }
914
915 /* copy the result from vector C into the pResult. */
916 for(i = 0; i < len; i++) {
917 buffer[i] = REG(result_vector + 4 * i);
918 }
919
920 return PKA_STATUS_SUCCESS;
921}
922/*---------------------------------------------------------------------------*/
923uint8_t
924bignum_divide_start(const uint32_t *dividend,
925 const uint8_t dividend_size,
926 const uint32_t *divisor,
927 const uint8_t divisor_size,
928 uint32_t *result_vector,
929 struct process *process)
930{
931
932 uint32_t offset;
933 uint32_t spacing;
934 int i;
935
936 /* We use largest len for spacing */
937 if(dividend_size > divisor_size) {
938 spacing = dividend_size;
939 } else {
940 spacing = divisor_size;
941 }
942 spacing += 2 + spacing % 2;
943
944 /* Check for the arguments. */
945 ASSERT(NULL != dividend);
946 ASSERT(NULL != divisor);
947 ASSERT(NULL != result_vector);
948
949 /* Make sure no operation is in progress. */
950 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
952 }
953
954 /* Update the A ptr with the offset address of the PKA RAM location
955 * where the multiplicand will be stored. */
956 offset = 0;
957 REG(PKA_APTR) = offset >> 2;
958
959 /* Load the multiplicand in PKA RAM. */
960 for(i = 0; i < dividend_size; i++) {
961 REG(PKA_RAM_BASE + offset + 4 * i) = *dividend;
962 dividend++;
963 }
964
965 /* Determine the offset for the next data. */
966 offset += 4 * spacing;
967
968 /* Update the B ptr with the offset address of the PKA RAM location
969 * where the multiplier will be stored. */
970 REG(PKA_BPTR) = offset >> 2;
971
972 /* Load the multiplier in PKA RAM. */
973 for(i = 0; i < divisor_size; i++) {
974 REG(PKA_RAM_BASE + offset + 4 * i) = *divisor;
975 divisor++;
976 }
977
978 /* Determine the offset for the reminder. */
979 offset += 4 * spacing;
980
981 /* Load C ptr with the result location in PKA RAM. */
982 REG(PKA_CPTR) = offset >> 2;
983
984 /* Determine the offset for the quotient. */
985 offset += 4 * spacing;
986
987 /* Copy the quotient vector address location. */
988 *result_vector = PKA_RAM_BASE + offset;
989
990 /* Load D ptr with the result location in PKA RAM. */
991 REG(PKA_DPTR) = offset >> 2;
992
993 /* Load the respective length registers. */
994 REG(PKA_ALENGTH) = dividend_size;
995 REG(PKA_BLENGTH) = divisor_size;
996
997 /* Set the PKA function to the multiplication and start it. */
999
1000 /* Enable Interrupt */
1001 if(process != NULL) {
1003 NVIC_ClearPendingIRQ(PKA_IRQn);
1004 NVIC_EnableIRQ(PKA_IRQn);
1005 }
1006
1007 return PKA_STATUS_SUCCESS;
1008}
1009/*---------------------------------------------------------------------------*/
1010uint8_t
1012 uint32_t *buffer_size,
1013 const uint32_t result_vector)
1014{
1015
1016 uint32_t regMSWVal;
1017 uint32_t len;
1018 int i;
1019
1020 /* Check for arguments. */
1021 ASSERT(NULL != buffer);
1022 ASSERT(NULL != buffer_size);
1023 ASSERT(result_vector > PKA_RAM_BASE);
1024 ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
1025
1026 /* Verify that the operation is complete. */
1027 if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
1029 }
1030
1031 /* Disable Interrupt */
1032 NVIC_DisableIRQ(PKA_IRQn);
1034
1035 /* Get the MSW register value. */
1036 regMSWVal = REG(PKA_MSW);
1037
1038 /* Check to make sure that the result vector is not all zeroes. */
1039 if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
1040 return PKA_STATUS_RESULT_0;
1041 }
1042
1043 /* Get the length of the result. */
1044 len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
1045 - ((result_vector - PKA_RAM_BASE) >> 2);
1046
1047 /* Make sure that the length of the supplied result buffer is adequate
1048 * to store the resultant. */
1049 if(*buffer_size < len) {
1051 }
1052
1053 /* Copy the resultant length. */
1054 *buffer_size = len;
1055
1056 /* Copy the result from vector C into the pResult. */
1057 for(i = 0; i < *buffer_size; i++) {
1058 buffer[i] = REG(result_vector + 4 * i);
1059 }
1060
1061 return PKA_STATUS_SUCCESS;
1062}
1063/** @} */
1064
Header file for the cc2538 BigNum driver.
@ PKA_IRQn
PKA Interrupt.
Definition cc2538_cm3.h:112
uint8_t bignum_add_get_result(uint32_t *buffer, uint32_t *buffer_size, const uint32_t result_vector)
Gets the result of the addition operation on two big number.
uint8_t bignum_inv_mod_get_result(uint32_t *buffer, const uint8_t buffer_size, const uint32_t result_vector)
Gets the result of the big number inverse modulo operation.
uint8_t bignum_inv_mod_start(const uint32_t *number, const uint8_t number_size, const uint32_t *modulus, const uint8_t modulus_size, uint32_t *result_vector, struct process *process)
Starts the big number inverse modulo operation.
uint8_t bignum_divide_start(const uint32_t *dividend, const uint8_t dividend_size, const uint32_t *divisor, const uint8_t divisor_size, uint32_t *result_vector, struct process *process)
Starts the big number Divide.
uint8_t bignum_exp_mod_get_result(uint32_t *buffer, const uint8_t buffer_size, const uint32_t result_vector)
Gets the result of the big number modulus operation result.
uint8_t bignum_mul_start(const uint32_t *multiplicand, const uint8_t multiplicand_size, const uint32_t *multiplier, const uint8_t multiplier_size, uint32_t *result_vector, struct process *process)
Starts the big number multiplication.
uint8_t bignum_add_start(const uint32_t *number1, const uint8_t number1_size, const uint32_t *number2, const uint8_t number2_size, uint32_t *result_vector, struct process *process)
Starts the addition of two big number.
uint8_t bignum_mod_start(const uint32_t *number, const uint8_t number_size, const uint32_t *modulus, const uint8_t modulus_size, uint32_t *result_vector, struct process *process)
Starts the big number modulus operation.
uint8_t bignum_cmp_get_result(void)
Gets the result of the comparison operation of two big numbers.
uint8_t bignum_exp_mod_start(const uint32_t *number, const uint8_t number_size, const uint32_t *modulus, const uint8_t modulus_size, const uint32_t *base, const uint8_t base_size, uint32_t *result_vector, struct process *process)
Starts the big number moduluar Exponentiation operation.
uint8_t bignum_mul_get_result(uint32_t *buffer, uint32_t *buffer_size, const uint32_t result_vector)
Gets the results of the big number multiplication.
uint8_t bignum_divide_get_result(uint32_t *buffer, uint32_t *buffer_size, const uint32_t result_vector)
Gets the results of the big number Divide.
uint8_t bignum_subtract_start(const uint32_t *number1, const uint8_t number1_size, const uint32_t *number2, const uint8_t number2_size, uint32_t *result_vector, struct process *process)
Starts the substract of two big number.
uint8_t bignum_mod_get_result(uint32_t *buffer, const uint8_t buffer_size, const uint32_t result_vector)
Gets the result of the big number modulus operation.
uint8_t bignum_subtract_get_result(uint32_t *buffer, uint32_t *buffer_size, const uint32_t result_vector)
Gets the result of big number subtract.
uint8_t bignum_cmp_start(const uint32_t *number1, const uint32_t *number2, const uint8_t size, struct process *process)
Starts the comparison of two big numbers.
#define PKA_FUNCTION_RUN
The host sets this bit to instruct the PKA module to begin processing the basic PKCP or complex seque...
Definition pka.h:438
#define PKA_STATUS_BUF_UNDERFLOW
Buffer underflow.
Definition pka.h:820
#define PKA_CPTR
PKA vector C address During execution of basic PKCP operations, this register is double buffered and ...
Definition pka.h:100
#define PKA_FUNCTION_ADD
Perform add operation.
Definition pka.h:513
#define PKA_STATUS_A_LT_B
Big number compare return status if the first big num is less than the second.
Definition pka.h:825
#define PKA_COMPARE_A_LESS_THAN_B
Vector_A is less than Vector_B.
Definition pka.h:545
#define PKA_DPTR
PKA vector D address During execution of basic PKCP operations, this register is double buffered and ...
Definition pka.h:115
#define PKA_DIVMSW
PKA most-significant-word of divide remainder This register indicates the (32-bit word) address in th...
Definition pka.h:229
#define PKA_STATUS_A_GR_B
Big number compare return status if the first big num is greater than the second.
Definition pka.h:822
#define PKA_FUNCTION_MULTIPLY
Perform multiply operation.
Definition pka.h:530
#define PKA_FUNCTION
PKA function This register contains the control bits to start basic PKCP as well as complex sequencer...
Definition pka.h:173
#define PKA_RAM_SIZE
PKA Memory Size.
Definition pka.h:58
#define PKA_STATUS_OPERATION_INPRG
PKA operation is in progress.
Definition pka.h:828
#define PKA_MSW
PKA most-significant-word of result vector This register indicates the (word) address in the PKA RAM ...
Definition pka.h:206
void pka_register_process_notification(struct process *p)
Registers a process to be notified of the completion of a PKA operation.
Definition pka.c:119
#define PKA_FUNCTION_COMPARE
Perform compare operation.
Definition pka.h:495
#define PKA_MSW_MSW_ADDRESS_M
Address of the most-significant nonzero 32-bit word of the result vector in PKA RAM.
Definition pka.h:566
#define PKA_RAM_BASE
PKA Memory Address.
Definition pka.h:57
#define PKA_BLENGTH
PKA vector B length During execution of basic PKCP operations, this register is double buffered and c...
Definition pka.h:145
#define PKA_FUNCTION_DIVIDE
Perform divide operation.
Definition pka.h:501
#define PKA_ALENGTH
PKA vector A length During execution of basic PKCP operations, this register is double buffered and c...
Definition pka.h:130
#define PKA_APTR
PKA vector A address During execution of basic PKCP operations, this register is double buffered and ...
Definition pka.h:70
#define PKA_DIVMSW_MSW_ADDRESS_M
Address of the most significant nonzero 32-bit word of the remainder result vector in PKA RAM.
Definition pka.h:583
#define PKA_STATUS_FAILURE
Failure.
Definition pka.h:818
#define PKA_FUNCTION_MODULO
Perform modulo operation.
Definition pka.h:498
#define PKA_COMPARE
PKA compare result This register provides the result of a basic PKCP compare operation.
Definition pka.h:197
#define PKA_COMPARE_A_GREATER_THAN_B
Vector_A is greater than Vector_B.
Definition pka.h:538
#define PKA_COMPARE_A_EQUALS_B
Vector_A is equal to Vector_B.
Definition pka.h:551
#define PKA_MSW_RESULT_IS_ZERO
The result vector is all zeroes, ignore the address returned in bits [10:0].
Definition pka.h:560
#define PKA_STATUS_RESULT_0
Result is all zeros.
Definition pka.h:821
#define PKA_DIVMSW_RESULT_IS_ZERO
The result vector is all zeroes, ignore the address returned in bits [10:0].
Definition pka.h:575
#define PKA_BPTR
PKA vector B address During execution of basic PKCP operations, this register is double buffered and ...
Definition pka.h:85
#define PKA_FUNCTION_SUBTRACT
Perform subtract operation.
Definition pka.h:510
#define PKA_STATUS_SUCCESS
Success.
Definition pka.h:817
Header file for the ARM Nested Vectored Interrupt Controller.
Header file with register manipulation macro definitions.