Contiki-NG
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 /*---------------------------------------------------------------------------*/
63 uint8_t
64 bignum_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. */
128  REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_MODULO);
129 
130  /* Enable Interrupt */
131  if(process != NULL) {
135  }
136 
137  return PKA_STATUS_SUCCESS;
138 }
139 /*---------------------------------------------------------------------------*/
140 uint8_t
141 bignum_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 */
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 /*---------------------------------------------------------------------------*/
189 uint8_t
190 bignum_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. */
236  REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_COMPARE);
237 
238  /* Enable Interrupt */
239  if(process != NULL) {
243  }
244 
245  return PKA_STATUS_SUCCESS;
246 }
247 /*---------------------------------------------------------------------------*/
248 uint8_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 */
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 /*---------------------------------------------------------------------------*/
285 uint8_t
286 bignum_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) {
351  }
352 
353  return PKA_STATUS_SUCCESS;
354 }
355 /*---------------------------------------------------------------------------*/
356 uint8_t
357 bignum_inv_mod_get_result(uint32_t *buffer,
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 */
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 /*---------------------------------------------------------------------------*/
406 uint8_t
407 bignum_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. */
467  REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_MULTIPLY);
468 
469  /* Enable Interrupt */
470  if(process != NULL) {
474  }
475 
476  return PKA_STATUS_SUCCESS;
477 }
478 /*---------------------------------------------------------------------------*/
479 uint8_t
480 bignum_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 */
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 /*---------------------------------------------------------------------------*/
533 uint8_t
534 bignum_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. */
592  REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_ADD);
593 
594  /* Enable Interrupt */
595  if(process != NULL) {
599  }
600 
601  return PKA_STATUS_SUCCESS;
602 }
603 /*---------------------------------------------------------------------------*/
604 uint8_t
605 bignum_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 */
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 */
659 uint8_t
660 bignum_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. */
718  REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_SUBTRACT);
719 
720  /* Enable Interrupt */
721  if(process != NULL) {
725  }
726 
727  return PKA_STATUS_SUCCESS;
728 }
729 /*---------------------------------------------------------------------------*/
730 uint8_t
731 bignum_subtract_get_result(uint32_t *buffer,
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 */
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 /*---------------------------------------------------------------------------*/
784 uint8_t
785 bignum_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) {
869  }
870 
871  return PKA_STATUS_SUCCESS;
872 }
873 /*---------------------------------------------------------------------------*/
874 uint8_t
875 bignum_exp_mod_get_result(uint32_t *buffer,
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 */
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 /*---------------------------------------------------------------------------*/
923 uint8_t
924 bignum_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. */
998  REG(PKA_FUNCTION) = (PKA_FUNCTION_RUN | PKA_FUNCTION_DIVIDE);
999 
1000  /* Enable Interrupt */
1001  if(process != NULL) {
1005  }
1006 
1007  return PKA_STATUS_SUCCESS;
1008 }
1009 /*---------------------------------------------------------------------------*/
1010 uint8_t
1011 bignum_divide_get_result(uint32_t *buffer,
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 */
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) {
1050  return PKA_STATUS_BUF_UNDERFLOW;
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 
#define PKA_FUNCTION_COMPARE
Perform compare operation.
Definition: pka.h:837
uint8_t bignum_cmp_get_result(void)
Gets the result of the comparison operation of two big numbers.
#define PKA_DIVMSW_RESULT_IS_ZERO
The result vector is all zeroes, ignore the address returned in bits [10:0].
Definition: pka.h:930
#define PKA_STATUS_SUCCESS
Success.
Definition: pka.h:1296
Header file for the ARM Nested Vectored Interrupt Controller.
#define PKA_STATUS_BUF_UNDERFLOW
Buffer underflow.
Definition: pka.h:1299
#define PKA_FUNCTION_DIVIDE
Perform divide operation.
Definition: pka.h:843
#define PKA_FUNCTION_SUBTRACT
Perform subtract operation.
Definition: pka.h:852
#define PKA_STATUS_A_LT_B
Big number compare return status if the first big num is less than the second.
Definition: pka.h:1306
#define PKA_FUNCTION
PKA function This register contains the control bits to start basic PKCP as well as complex sequencer...
Definition: pka.h:273
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.
#define PKA_STATUS_FAILURE
Failure.
Definition: pka.h:1297
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.
#define PKA_DIVMSW
PKA most-significant-word of divide remainder This register indicates the (32-bit word) address in th...
Definition: pka.h:382
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.
#define PKA_COMPARE
PKA compare result This register provides the result of a basic PKCP compare operation.
Definition: pka.h:320
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.
Header file with register manipulation macro definitions.
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.
Definition: bignum-driver.c:64
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.
#define PKA_STATUS_A_GR_B
Big number compare return status if the first big num is greater than the second. ...
Definition: pka.h:1301
#define PKA_RAM_BASE
PKA Memory Address.
Definition: pka.h:57
#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:940
#define PKA_FUNCTION_ADD
Perform add operation.
Definition: pka.h:855
#define PKA_CPTR
PKA vector C address During execution of basic PKCP operations, this register is double buffered and ...
Definition: pka.h:132
__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
Disable External Interrupt.
Definition: core_cm0.h:653
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.
#define PKA_FUNCTION_MODULO
Perform modulo operation.
Definition: pka.h:840
#define PKA_STATUS_RESULT_0
Result is all zeros.
Definition: pka.h:1300
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.
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
Enable External Interrupt.
Definition: core_cm0.h:642
PKA Interrupt.
Definition: cc2538_cm3.h:112
#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:919
#define PKA_ALENGTH
PKA vector A length During execution of basic PKCP operations, this register is double buffered and c...
Definition: pka.h:190
#define PKA_FUNCTION_MULTIPLY
Perform multiply operation.
Definition: pka.h:880
__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
Clear Pending Interrupt.
Definition: core_cm0.h:688
#define PKA_COMPARE_A_LESS_THAN_B
Vector_A is less than Vector_B.
Definition: pka.h:896
#define PKA_STATUS_OPERATION_INPRG
PKA operation is in progress.
Definition: pka.h:1311
#define PKA_BLENGTH
PKA vector B length During execution of basic PKCP operations, this register is double buffered and c...
Definition: pka.h:219
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_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_APTR
PKA vector A address During execution of basic PKCP operations, this register is double buffered and ...
Definition: pka.h:74
#define PKA_COMPARE_A_GREATER_THAN_B
Vector_A is greater than Vector_B.
Definition: pka.h:888
#define PKA_COMPARE_A_EQUALS_B
Vector_A is equal to Vector_B.
Definition: pka.h:902
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.
#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:733
#define PKA_MSW
PKA most-significant-word of result vector This register indicates the (word) address in the PKA RAM ...
Definition: pka.h:337
#define PKA_DPTR
PKA vector D address During execution of basic PKCP operations, this register is double buffered and ...
Definition: pka.h:161
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
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.
#define PKA_RAM_SIZE
PKA Memory Size.
Definition: pka.h:58
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_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.
#define PKA_MSW_RESULT_IS_ZERO
The result vector is all zeroes, ignore the address returned in bits [10:0].
Definition: pka.h:911
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.
#define PKA_BPTR
PKA vector B address During execution of basic PKCP operations, this register is double buffered and ...
Definition: pka.h:103
Header file for the cc2538 BigNum driver.