stm32f4xx_cryp.c 33.7 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
/**
  ******************************************************************************
  * @file    stm32f4xx_cryp.c
  * @author  MCD Application Team
  * @version V1.5.0
  * @date    06-March-2015
  * @brief   This file provides firmware functions to manage the following 
  *          functionalities of the  Cryptographic processor (CRYP) peripheral:
  *           + Initialization and Configuration functions
  *           + Data treatment functions 
  *           + Context swapping functions     
  *           + DMA interface function       
  *           + Interrupts and flags management       
  *
@verbatim
 ===================================================================      
                 ##### How to use this driver #####
 =================================================================== 
 [..]
   (#) Enable the CRYP controller clock using 
       RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_CRYP, ENABLE); function.
  
   (#) Initialize the CRYP using CRYP_Init(), CRYP_KeyInit() and if needed 
       CRYP_IVInit(). 
  
   (#) Flush the IN and OUT FIFOs by using CRYP_FIFOFlush() function.
  
   (#) Enable the CRYP controller using the CRYP_Cmd() function. 
  
   (#) If using DMA for Data input and output transfer, activate the needed DMA 
       Requests using CRYP_DMACmd() function 
  
   (#) If DMA is not used for data transfer, use CRYP_DataIn() and  CRYP_DataOut() 
       functions to enter data to IN FIFO and get result from OUT FIFO.
  
   (#) To control CRYP events you can use one of the following two methods:
       (++) Check on CRYP flags using the CRYP_GetFlagStatus() function.  
       (++) Use CRYP interrupts through the function CRYP_ITConfig() at 
            initialization phase and CRYP_GetITStatus() function into interrupt 
            routines in processing phase.
         
   (#) Save and restore Cryptographic processor context using CRYP_SaveContext() 
       and CRYP_RestoreContext() functions.     
  
  
 *** Procedure to perform an encryption or a decryption ***
 ========================================================== 
  
 *** Initialization ***
 ====================== 
 [..] 
   (#) Initialize the peripheral using CRYP_Init(), CRYP_KeyInit() and CRYP_IVInit 
       functions:
       (++) Configure the key size (128-, 192- or 256-bit, in the AES only) 
       (++) Enter the symmetric key 
       (++) Configure the data type
       (++) In case of decryption in AES-ECB or AES-CBC, you must prepare 
            the key: configure the key preparation mode. Then Enable the CRYP 
            peripheral using CRYP_Cmd() function: the BUSY flag is set. 
            Wait until BUSY flag is reset : the key is prepared for decryption
       (++) Configure the algorithm and chaining (the DES/TDES in ECB/CBC, the 
            AES in ECB/CBC/CTR) 
       (++) Configure the direction (encryption/decryption).
       (++) Write the initialization vectors (in CBC or CTR modes only)
  
   (#) Flush the IN and OUT FIFOs using the CRYP_FIFOFlush() function
  
  
  *** Basic Processing mode (polling mode) *** 
  ============================================  
  [..]
    (#) Enable the cryptographic processor using CRYP_Cmd() function.
  
    (#) Write the first blocks in the input FIFO (2 to 8 words) using 
        CRYP_DataIn() function.
  
    (#) Repeat the following sequence until the complete message has been 
        processed:
  
        (++) Wait for flag CRYP_FLAG_OFNE occurs (using CRYP_GetFlagStatus() 
            function), then read the OUT-FIFO using CRYP_DataOut() function
            (1 block or until the FIFO is empty)
  
         (++) Wait for flag CRYP_FLAG_IFNF occurs, (using CRYP_GetFlagStatus() 
            function then write the IN FIFO using CRYP_DataIn() function 
            (1 block or until the FIFO is full)
  
    (#) At the end of the processing, CRYP_FLAG_BUSY flag will be reset and 
          both FIFOs are empty (CRYP_FLAG_IFEM is set and CRYP_FLAG_OFNE is 
          reset). You can disable the peripheral using CRYP_Cmd() function.
  
 *** Interrupts Processing mode *** 
 ==================================
 [..] In this mode, Processing is done when the data are transferred by the 
      CPU during interrupts.
  
    (#) Enable the interrupts CRYP_IT_INI and CRYP_IT_OUTI using CRYP_ITConfig()
        function.
  
    (#) Enable the cryptographic processor using CRYP_Cmd() function.
  
    (#) In the CRYP_IT_INI interrupt handler : load the input message into the 
         IN FIFO using CRYP_DataIn() function . You can load 2 or 4 words at a 
         time, or load data until the IN FIFO is full. When the last word of
         the message has been entered into the IN FIFO, disable the CRYP_IT_INI 
         interrupt (using CRYP_ITConfig() function).
  
    (#) In the CRYP_IT_OUTI interrupt handler : read the output message from 
         the OUT FIFO using CRYP_DataOut() function. You can read 1 block (2 or 
         4 words) at a time or read data until the FIFO is empty.
         When the last word has been read, INIM=0, BUSY=0 and both FIFOs are 
         empty (CRYP_FLAG_IFEM is set and CRYP_FLAG_OFNE is reset). 
         You can disable the CRYP_IT_OUTI interrupt (using CRYP_ITConfig() 
         function) and you can disable the peripheral using CRYP_Cmd() function.
  
 *** DMA Processing mode *** 
 ===========================
 [..] In this mode, Processing is done when the DMA is used to transfer the 
      data from/to the memory.
  
    (#) Configure the DMA controller to transfer the input data from the 
         memory using DMA_Init() function. 
         The transfer length is the length of the message. 
         As message padding is not managed by the peripheral, the message 
         length must be an entire number of blocks. The data are transferred 
         in burst mode. The burst length is 4 words in the AES and 2 or 4 
         words in the DES/TDES. The DMA should be configured to set an 
         interrupt on transfer completion of the output data to indicate that 
         the processing is finished. 
         Refer to DMA peripheral driver for more details.  
  
     (#) Enable the cryptographic processor using CRYP_Cmd() function. 
         Enable the DMA requests CRYP_DMAReq_DataIN and CRYP_DMAReq_DataOUT 
         using CRYP_DMACmd() function.
  
     (#) All the transfers and processing are managed by the DMA and the 
         cryptographic processor. The DMA transfer complete interrupt indicates 
         that the processing is complete. Both FIFOs are normally empty and 
         CRYP_FLAG_BUSY flag is reset.
  
    @endverbatim
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software 
  * distributed under the License is distributed on an "AS IS" BASIS, 
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************  
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_cryp.h"
#include "stm32f4xx_rcc.h"

/** @addtogroup STM32F4xx_StdPeriph_Driver
  * @{
  */

/** @defgroup CRYP 
  * @brief CRYP driver modules
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define FLAG_MASK     ((uint8_t)0x20)
#define MAX_TIMEOUT   ((uint16_t)0xFFFF)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/** @defgroup CRYP_Private_Functions
  * @{
  */ 

/** @defgroup CRYP_Group1 Initialization and Configuration functions
 *  @brief    Initialization and Configuration functions 
 *
@verbatim    
 ===============================================================================
             ##### Initialization and Configuration functions #####
 ===============================================================================  
 [..] This section provides functions allowing to 
   (+) Initialize the cryptographic Processor using CRYP_Init() function 
       (++)  Encrypt or Decrypt 
       (++)  mode : TDES-ECB, TDES-CBC, 
                    DES-ECB, DES-CBC, 
                    AES-ECB, AES-CBC, AES-CTR, AES-Key, AES-GCM, AES-CCM 
       (++) DataType :  32-bit data, 16-bit data, bit data or bit-string
       (++) Key Size (only in AES modes)
   (+) Configure the Encrypt or Decrypt Key using CRYP_KeyInit() function 
   (+) Configure the Initialization Vectors(IV) for CBC and CTR modes using 
       CRYP_IVInit() function.  
   (+) Flushes the IN and OUT FIFOs : using CRYP_FIFOFlush() function.                         
   (+) Enable or disable the CRYP Processor using CRYP_Cmd() function 
       
@endverbatim
  * @{
  */
/**
  * @brief  Deinitializes the CRYP peripheral registers to their default reset values
  * @param  None
  * @retval None
  */
void CRYP_DeInit(void)
{
  /* Enable CRYP reset state */
  RCC_AHB2PeriphResetCmd(RCC_AHB2Periph_CRYP, ENABLE);

  /* Release CRYP from reset state */
  RCC_AHB2PeriphResetCmd(RCC_AHB2Periph_CRYP, DISABLE);
}

/**
  * @brief  Initializes the CRYP peripheral according to the specified parameters
  *         in the CRYP_InitStruct.
  * @param  CRYP_InitStruct: pointer to a CRYP_InitTypeDef structure that contains
  *         the configuration information for the CRYP peripheral.
  * @retval None
  */
void CRYP_Init(CRYP_InitTypeDef* CRYP_InitStruct)
{
  /* Check the parameters */
  assert_param(IS_CRYP_ALGOMODE(CRYP_InitStruct->CRYP_AlgoMode));
  assert_param(IS_CRYP_DATATYPE(CRYP_InitStruct->CRYP_DataType));
  assert_param(IS_CRYP_ALGODIR(CRYP_InitStruct->CRYP_AlgoDir));

  /* Select Algorithm mode*/  
  CRYP->CR &= ~CRYP_CR_ALGOMODE;
  CRYP->CR |= CRYP_InitStruct->CRYP_AlgoMode;

  /* Select dataType */ 
  CRYP->CR &= ~CRYP_CR_DATATYPE;
  CRYP->CR |= CRYP_InitStruct->CRYP_DataType;

  /* select Key size (used only with AES algorithm) */
  if ((CRYP_InitStruct->CRYP_AlgoMode != CRYP_AlgoMode_TDES_ECB) &&
      (CRYP_InitStruct->CRYP_AlgoMode != CRYP_AlgoMode_TDES_CBC) &&
      (CRYP_InitStruct->CRYP_AlgoMode != CRYP_AlgoMode_DES_ECB) &&
      (CRYP_InitStruct->CRYP_AlgoMode != CRYP_AlgoMode_DES_CBC))
  {
    assert_param(IS_CRYP_KEYSIZE(CRYP_InitStruct->CRYP_KeySize));
    CRYP->CR &= ~CRYP_CR_KEYSIZE;
    CRYP->CR |= CRYP_InitStruct->CRYP_KeySize; /* Key size and value must be 
                                                  configured once the key has 
                                                  been prepared */
  }

  /* Select data Direction */ 
  CRYP->CR &= ~CRYP_CR_ALGODIR;
  CRYP->CR |= CRYP_InitStruct->CRYP_AlgoDir;
}

/**
  * @brief  Fills each CRYP_InitStruct member with its default value.
  * @param  CRYP_InitStruct: pointer to a CRYP_InitTypeDef structure which will
  *         be initialized.
  * @retval None
  */
void CRYP_StructInit(CRYP_InitTypeDef* CRYP_InitStruct)
{
  /* Initialize the CRYP_AlgoDir member */
  CRYP_InitStruct->CRYP_AlgoDir = CRYP_AlgoDir_Encrypt;

  /* initialize the CRYP_AlgoMode member */
  CRYP_InitStruct->CRYP_AlgoMode = CRYP_AlgoMode_TDES_ECB;

  /* initialize the CRYP_DataType member */
  CRYP_InitStruct->CRYP_DataType = CRYP_DataType_32b;
  
  /* Initialize the CRYP_KeySize member */
  CRYP_InitStruct->CRYP_KeySize = CRYP_KeySize_128b;
}

/**
  * @brief  Initializes the CRYP Keys according to the specified parameters in
  *         the CRYP_KeyInitStruct.
  * @param  CRYP_KeyInitStruct: pointer to a CRYP_KeyInitTypeDef structure that
  *         contains the configuration information for the CRYP Keys.
  * @retval None
  */
void CRYP_KeyInit(CRYP_KeyInitTypeDef* CRYP_KeyInitStruct)
{
  /* Key Initialisation */
  CRYP->K0LR = CRYP_KeyInitStruct->CRYP_Key0Left;
  CRYP->K0RR = CRYP_KeyInitStruct->CRYP_Key0Right;
  CRYP->K1LR = CRYP_KeyInitStruct->CRYP_Key1Left;
  CRYP->K1RR = CRYP_KeyInitStruct->CRYP_Key1Right;
  CRYP->K2LR = CRYP_KeyInitStruct->CRYP_Key2Left;
  CRYP->K2RR = CRYP_KeyInitStruct->CRYP_Key2Right;
  CRYP->K3LR = CRYP_KeyInitStruct->CRYP_Key3Left;
  CRYP->K3RR = CRYP_KeyInitStruct->CRYP_Key3Right;
}

/**
  * @brief  Fills each CRYP_KeyInitStruct member with its default value.
  * @param  CRYP_KeyInitStruct: pointer to a CRYP_KeyInitTypeDef structure 
  *         which will be initialized.
  * @retval None
  */
void CRYP_KeyStructInit(CRYP_KeyInitTypeDef* CRYP_KeyInitStruct)
{
  CRYP_KeyInitStruct->CRYP_Key0Left  = 0;
  CRYP_KeyInitStruct->CRYP_Key0Right = 0;
  CRYP_KeyInitStruct->CRYP_Key1Left  = 0;
  CRYP_KeyInitStruct->CRYP_Key1Right = 0;
  CRYP_KeyInitStruct->CRYP_Key2Left  = 0;
  CRYP_KeyInitStruct->CRYP_Key2Right = 0;
  CRYP_KeyInitStruct->CRYP_Key3Left  = 0;
  CRYP_KeyInitStruct->CRYP_Key3Right = 0;
}
/**
  * @brief  Initializes the CRYP Initialization Vectors(IV) according to the
  *         specified parameters in the CRYP_IVInitStruct.
  * @param  CRYP_IVInitStruct: pointer to a CRYP_IVInitTypeDef structure that contains
  *         the configuration information for the CRYP Initialization Vectors(IV).
  * @retval None
  */
void CRYP_IVInit(CRYP_IVInitTypeDef* CRYP_IVInitStruct)
{
  CRYP->IV0LR = CRYP_IVInitStruct->CRYP_IV0Left;
  CRYP->IV0RR = CRYP_IVInitStruct->CRYP_IV0Right;
  CRYP->IV1LR = CRYP_IVInitStruct->CRYP_IV1Left;
  CRYP->IV1RR = CRYP_IVInitStruct->CRYP_IV1Right;
}

/**
  * @brief  Fills each CRYP_IVInitStruct member with its default value.
  * @param  CRYP_IVInitStruct: pointer to a CRYP_IVInitTypeDef Initialization 
  *         Vectors(IV) structure which will be initialized.
  * @retval None
  */
void CRYP_IVStructInit(CRYP_IVInitTypeDef* CRYP_IVInitStruct)
{
  CRYP_IVInitStruct->CRYP_IV0Left  = 0;
  CRYP_IVInitStruct->CRYP_IV0Right = 0;
  CRYP_IVInitStruct->CRYP_IV1Left  = 0;
  CRYP_IVInitStruct->CRYP_IV1Right = 0;
}

/**
  * @brief  Configures the AES-CCM and AES-GCM phases
  * @note   This function is used only with AES-CCM or AES-GCM Algorithms  
  * @param  CRYP_Phase: specifies the CRYP AES-CCM and AES-GCM phase to be configured.
  *           This parameter can be one of the following values:
  *            @arg CRYP_Phase_Init: Initialization phase
  *            @arg CRYP_Phase_Header: Header phase
  *            @arg CRYP_Phase_Payload: Payload phase
  *            @arg CRYP_Phase_Final: Final phase 
  * @retval None
  */
void CRYP_PhaseConfig(uint32_t CRYP_Phase)
{ uint32_t tempcr = 0;

  /* Check the parameter */
  assert_param(IS_CRYP_PHASE(CRYP_Phase));

  /* Get the CR register */
  tempcr = CRYP->CR;
  
  /* Reset the phase configuration bits: GCMP_CCMPH */
  tempcr &= (uint32_t)(~CRYP_CR_GCM_CCMPH);
  /* Set the selected phase */
  tempcr |= (uint32_t)CRYP_Phase;

  /* Set the CR register */ 
  CRYP->CR = tempcr;    
}

/**
  * @brief  Flushes the IN and OUT FIFOs (that is read and write pointers of the 
  *         FIFOs are reset)
  * @note   The FIFOs must be flushed only when BUSY flag is reset.  
  * @param  None
  * @retval None
  */
void CRYP_FIFOFlush(void)
{
  /* Reset the read and write pointers of the FIFOs */
  CRYP->CR |= CRYP_CR_FFLUSH;
}

/**
  * @brief  Enables or disables the CRYP peripheral.
  * @param  NewState: new state of the CRYP peripheral.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void CRYP_Cmd(FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    /* Enable the Cryptographic processor */
    CRYP->CR |= CRYP_CR_CRYPEN;
  }
  else
  {
    /* Disable the Cryptographic processor */
    CRYP->CR &= ~CRYP_CR_CRYPEN;
  }
}
/**
  * @}
  */
  
/** @defgroup CRYP_Group2 CRYP Data processing functions
 *  @brief    CRYP Data processing functions
 *
@verbatim    
 ===============================================================================
                    ##### CRYP Data processing functions #####
 ===============================================================================  
 [..] This section provides functions allowing the encryption and decryption 
      operations: 
   (+) Enter data to be treated in the IN FIFO : using CRYP_DataIn() function.
   (+) Get the data result from the OUT FIFO : using CRYP_DataOut() function.

@endverbatim
  * @{
  */

/**
  * @brief  Writes data in the Data Input register (DIN).
  * @note   After the DIN register has been read once or several times, 
  *         the FIFO must be flushed (using CRYP_FIFOFlush() function).  
  * @param  Data: data to write in Data Input register
  * @retval None
  */
void CRYP_DataIn(uint32_t Data)
{
  CRYP->DR = Data;
}

/**
  * @brief  Returns the last data entered into the output FIFO.
  * @param  None
  * @retval Last data entered into the output FIFO.
  */
uint32_t CRYP_DataOut(void)
{
  return CRYP->DOUT;
}
/**
  * @}
  */
  
/** @defgroup CRYP_Group3 Context swapping functions
 *  @brief   Context swapping functions
 *
@verbatim   
 ===============================================================================
                      ##### Context swapping functions #####
 ===============================================================================  
 [..] This section provides functions allowing to save and store CRYP Context

 [..] It is possible to interrupt an encryption/ decryption/ key generation process 
      to perform another processing with a higher priority, and to complete the 
      interrupted process later on, when the higher-priority task is complete. To do 
      so, the context of the interrupted task must be saved from the CRYP registers 
      to memory, and then be restored from memory to the CRYP registers.
   
   (#) To save the current context, use CRYP_SaveContext() function
   (#) To restore the saved context, use CRYP_RestoreContext() function 

@endverbatim
  * @{
  */
  
/**
  * @brief  Saves the CRYP peripheral Context. 
  * @note   This function stops DMA transfer before to save the context. After 
  *         restoring the context, you have to enable the DMA again (if the DMA
  *         was previously used).
  * @param  CRYP_ContextSave: pointer to a CRYP_Context structure that contains
  *         the repository for current context.
  * @param  CRYP_KeyInitStruct: pointer to a CRYP_KeyInitTypeDef structure that 
  *         contains the configuration information for the CRYP Keys.  
  * @retval None
  */
ErrorStatus CRYP_SaveContext(CRYP_Context* CRYP_ContextSave,
                             CRYP_KeyInitTypeDef* CRYP_KeyInitStruct)
{
  __IO uint32_t timeout = 0;
  uint32_t ckeckmask = 0, bitstatus;    
  ErrorStatus status = ERROR;

  /* Stop DMA transfers on the IN FIFO by clearing the DIEN bit in the CRYP_DMACR */
  CRYP->DMACR &= ~(uint32_t)CRYP_DMACR_DIEN;
    
  /* Wait until both the IN and OUT FIFOs are empty  
    (IFEM=1 and OFNE=0 in the CRYP_SR register) and the 
     BUSY bit is cleared. */

  if ((CRYP->CR & (uint32_t)(CRYP_CR_ALGOMODE_TDES_ECB | CRYP_CR_ALGOMODE_TDES_CBC)) != (uint32_t)0 )/* TDES */
  { 
    ckeckmask =  CRYP_SR_IFEM | CRYP_SR_BUSY ;
  }
  else /* AES or DES */
  {
    ckeckmask =  CRYP_SR_IFEM | CRYP_SR_BUSY | CRYP_SR_OFNE;
  }           
   
  do 
  {
    bitstatus = CRYP->SR & ckeckmask;
    timeout++;
  }
  while ((timeout != MAX_TIMEOUT) && (bitstatus != CRYP_SR_IFEM));
     
  if ((CRYP->SR & ckeckmask) != CRYP_SR_IFEM)
  {
    status = ERROR;
  }
  else
  {      
    /* Stop DMA transfers on the OUT FIFO by 
       - writing the DOEN bit to 0 in the CRYP_DMACR register 
       - and clear the CRYPEN bit. */

    CRYP->DMACR &= ~(uint32_t)CRYP_DMACR_DOEN;
    CRYP->CR &= ~(uint32_t)CRYP_CR_CRYPEN;

    /* Save the current configuration (bit 19, bit[17:16] and bits [9:2] in the CRYP_CR register) */
    CRYP_ContextSave->CR_CurrentConfig  = CRYP->CR & (CRYP_CR_GCM_CCMPH |
                                                      CRYP_CR_KEYSIZE  |
                                                      CRYP_CR_DATATYPE |
                                                      CRYP_CR_ALGOMODE |
                                                      CRYP_CR_ALGODIR);

    /* and, if not in ECB mode, the initialization vectors. */
    CRYP_ContextSave->CRYP_IV0LR = CRYP->IV0LR;
    CRYP_ContextSave->CRYP_IV0RR = CRYP->IV0RR;
    CRYP_ContextSave->CRYP_IV1LR = CRYP->IV1LR;
    CRYP_ContextSave->CRYP_IV1RR = CRYP->IV1RR;

    /* save The key value */
    CRYP_ContextSave->CRYP_K0LR = CRYP_KeyInitStruct->CRYP_Key0Left; 
    CRYP_ContextSave->CRYP_K0RR = CRYP_KeyInitStruct->CRYP_Key0Right; 
    CRYP_ContextSave->CRYP_K1LR = CRYP_KeyInitStruct->CRYP_Key1Left; 
    CRYP_ContextSave->CRYP_K1RR = CRYP_KeyInitStruct->CRYP_Key1Right; 
    CRYP_ContextSave->CRYP_K2LR = CRYP_KeyInitStruct->CRYP_Key2Left; 
    CRYP_ContextSave->CRYP_K2RR = CRYP_KeyInitStruct->CRYP_Key2Right; 
    CRYP_ContextSave->CRYP_K3LR = CRYP_KeyInitStruct->CRYP_Key3Left; 
    CRYP_ContextSave->CRYP_K3RR = CRYP_KeyInitStruct->CRYP_Key3Right; 

    /* Save the content of context swap registers */
    CRYP_ContextSave->CRYP_CSGCMCCMR[0] = CRYP->CSGCMCCM0R;
    CRYP_ContextSave->CRYP_CSGCMCCMR[1] = CRYP->CSGCMCCM1R;
    CRYP_ContextSave->CRYP_CSGCMCCMR[2] = CRYP->CSGCMCCM2R;
    CRYP_ContextSave->CRYP_CSGCMCCMR[3] = CRYP->CSGCMCCM3R;
    CRYP_ContextSave->CRYP_CSGCMCCMR[4] = CRYP->CSGCMCCM4R;
    CRYP_ContextSave->CRYP_CSGCMCCMR[5] = CRYP->CSGCMCCM5R;
    CRYP_ContextSave->CRYP_CSGCMCCMR[6] = CRYP->CSGCMCCM6R;
    CRYP_ContextSave->CRYP_CSGCMCCMR[7] = CRYP->CSGCMCCM7R;
    
    CRYP_ContextSave->CRYP_CSGCMR[0] = CRYP->CSGCM0R;
    CRYP_ContextSave->CRYP_CSGCMR[1] = CRYP->CSGCM1R;
    CRYP_ContextSave->CRYP_CSGCMR[2] = CRYP->CSGCM2R;
    CRYP_ContextSave->CRYP_CSGCMR[3] = CRYP->CSGCM3R;
    CRYP_ContextSave->CRYP_CSGCMR[4] = CRYP->CSGCM4R;
    CRYP_ContextSave->CRYP_CSGCMR[5] = CRYP->CSGCM5R;
    CRYP_ContextSave->CRYP_CSGCMR[6] = CRYP->CSGCM6R;
    CRYP_ContextSave->CRYP_CSGCMR[7] = CRYP->CSGCM7R;
    
   /* When needed, save the DMA status (pointers for IN and OUT messages, 
      number of remaining bytes, etc.) */
     
    status = SUCCESS;
  }

   return status;
}

/**
  * @brief  Restores the CRYP peripheral Context.
  * @note   Since the DMA transfer is stopped in CRYP_SaveContext() function,
  *         after restoring the context, you have to enable the DMA again (if the
  *         DMA was previously used).  
  * @param  CRYP_ContextRestore: pointer to a CRYP_Context structure that contains
  *         the repository for saved context.
  * @note   The data that were saved during context saving must be rewritten into
  *         the IN FIFO.
  * @retval None
  */
void CRYP_RestoreContext(CRYP_Context* CRYP_ContextRestore)  
{

  /* Configure the processor with the saved configuration */
  CRYP->CR = CRYP_ContextRestore->CR_CurrentConfig;

  /* restore The key value */
  CRYP->K0LR = CRYP_ContextRestore->CRYP_K0LR; 
  CRYP->K0RR = CRYP_ContextRestore->CRYP_K0RR;
  CRYP->K1LR = CRYP_ContextRestore->CRYP_K1LR;
  CRYP->K1RR = CRYP_ContextRestore->CRYP_K1RR;
  CRYP->K2LR = CRYP_ContextRestore->CRYP_K2LR;
  CRYP->K2RR = CRYP_ContextRestore->CRYP_K2RR;
  CRYP->K3LR = CRYP_ContextRestore->CRYP_K3LR;
  CRYP->K3RR = CRYP_ContextRestore->CRYP_K3RR;

  /* and the initialization vectors. */
  CRYP->IV0LR = CRYP_ContextRestore->CRYP_IV0LR;
  CRYP->IV0RR = CRYP_ContextRestore->CRYP_IV0RR;
  CRYP->IV1LR = CRYP_ContextRestore->CRYP_IV1LR;
  CRYP->IV1RR = CRYP_ContextRestore->CRYP_IV1RR;

  /* Restore the content of context swap registers */
  CRYP->CSGCMCCM0R = CRYP_ContextRestore->CRYP_CSGCMCCMR[0];
  CRYP->CSGCMCCM1R = CRYP_ContextRestore->CRYP_CSGCMCCMR[1];
  CRYP->CSGCMCCM2R = CRYP_ContextRestore->CRYP_CSGCMCCMR[2];
  CRYP->CSGCMCCM3R = CRYP_ContextRestore->CRYP_CSGCMCCMR[3];
  CRYP->CSGCMCCM4R = CRYP_ContextRestore->CRYP_CSGCMCCMR[4];
  CRYP->CSGCMCCM5R = CRYP_ContextRestore->CRYP_CSGCMCCMR[5];
  CRYP->CSGCMCCM6R = CRYP_ContextRestore->CRYP_CSGCMCCMR[6];
  CRYP->CSGCMCCM7R = CRYP_ContextRestore->CRYP_CSGCMCCMR[7];
  
  CRYP->CSGCM0R = CRYP_ContextRestore->CRYP_CSGCMR[0];
  CRYP->CSGCM1R = CRYP_ContextRestore->CRYP_CSGCMR[1];
  CRYP->CSGCM2R = CRYP_ContextRestore->CRYP_CSGCMR[2];
  CRYP->CSGCM3R = CRYP_ContextRestore->CRYP_CSGCMR[3];
  CRYP->CSGCM4R = CRYP_ContextRestore->CRYP_CSGCMR[4];
  CRYP->CSGCM5R = CRYP_ContextRestore->CRYP_CSGCMR[5];
  CRYP->CSGCM6R = CRYP_ContextRestore->CRYP_CSGCMR[6];
  CRYP->CSGCM7R = CRYP_ContextRestore->CRYP_CSGCMR[7];
  
  /* Enable the cryptographic processor */
  CRYP->CR |= CRYP_CR_CRYPEN;
}
/**
  * @}
  */

/** @defgroup CRYP_Group4 CRYP's DMA interface Configuration function
 *  @brief   CRYP's DMA interface Configuration function 
 *
@verbatim   
 ===============================================================================
             ##### CRYP's DMA interface Configuration function #####
 ===============================================================================  
 [..] This section provides functions allowing to configure the DMA interface for 
      CRYP data input and output transfer.
   
 [..] When the DMA mode is enabled (using the CRYP_DMACmd() function), data can be 
      transferred:
   (+) From memory to the CRYP IN FIFO using the DMA peripheral by enabling 
       the CRYP_DMAReq_DataIN request.
   (+) From the CRYP OUT FIFO to the memory using the DMA peripheral by enabling 
       the CRYP_DMAReq_DataOUT request.

@endverbatim
  * @{
  */

/**
  * @brief  Enables or disables the CRYP DMA interface.
  * @param  CRYP_DMAReq: specifies the CRYP DMA transfer request to be enabled or disabled.
  *           This parameter can be any combination of the following values:
  *            @arg CRYP_DMAReq_DataOUT: DMA for outgoing(Tx) data transfer
  *            @arg CRYP_DMAReq_DataIN: DMA for incoming(Rx) data transfer
  * @param  NewState: new state of the selected CRYP DMA transfer request.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void CRYP_DMACmd(uint8_t CRYP_DMAReq, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_CRYP_DMAREQ(CRYP_DMAReq));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    /* Enable the selected CRYP DMA request */
    CRYP->DMACR |= CRYP_DMAReq;
  }
  else
  {
    /* Disable the selected CRYP DMA request */
    CRYP->DMACR &= (uint8_t)~CRYP_DMAReq;
  }
}
/**
  * @}
  */

/** @defgroup CRYP_Group5 Interrupts and flags management functions
 *  @brief   Interrupts and flags management functions
 *
@verbatim   
 ===============================================================================
              ##### Interrupts and flags management functions #####
 ===============================================================================  
 
 [..] This section provides functions allowing to configure the CRYP Interrupts and 
      to get the status and Interrupts pending bits.

 [..] The CRYP provides 2 Interrupts sources and 7 Flags:

 *** Flags : ***
 ===============
 [..] 
   (#) CRYP_FLAG_IFEM :  Set when Input FIFO is empty. This Flag is cleared only
       by hardware.
      
   (#) CRYP_FLAG_IFNF :  Set when Input FIFO is not full. This Flag is cleared 
       only by hardware.


   (#) CRYP_FLAG_INRIS  : Set when Input FIFO Raw interrupt is pending it gives 
       the raw interrupt state prior to masking of the input FIFO service interrupt.
       This Flag is cleared only by hardware.
     
   (#) CRYP_FLAG_OFNE   : Set when Output FIFO not empty. This Flag is cleared 
       only by hardware.
        
   (#) CRYP_FLAG_OFFU   : Set when Output FIFO is full. This Flag is cleared only 
       by hardware.
                           
   (#) CRYP_FLAG_OUTRIS : Set when Output FIFO Raw interrupt is pending it gives 
       the raw interrupt state prior to masking of the output FIFO service interrupt.
       This Flag is cleared only by hardware.
                               
   (#) CRYP_FLAG_BUSY   : Set when the CRYP core is currently processing a block 
       of data or a key preparation (for AES decryption). This Flag is cleared 
       only by hardware. To clear it, the CRYP core must be disabled and the last
       processing has completed. 

 *** Interrupts : ***
 ====================
 [..]
   (#) CRYP_IT_INI   : The input FIFO service interrupt is asserted when there 
      are less than 4 words in the input FIFO. This interrupt is associated to 
      CRYP_FLAG_INRIS flag.

      -@- This interrupt is cleared by performing write operations to the input FIFO 
          until it holds 4 or more words. The input FIFO service interrupt INMIS is 
          enabled with the CRYP enable bit. Consequently, when CRYP is disabled, the 
          INMIS signal is low even if the input FIFO is empty.



   (#) CRYP_IT_OUTI  : The output FIFO service interrupt is asserted when there 
       is one or more (32-bit word) data items in the output FIFO. This interrupt 
       is associated to CRYP_FLAG_OUTRIS flag.

       -@- This interrupt is cleared by reading data from the output FIFO until there 
           is no valid (32-bit) word left (that is, the interrupt follows the state 
           of the OFNE (output FIFO not empty) flag).

 *** Managing the CRYP controller events : ***
 =============================================
 [..] The user should identify which mode will be used in his application to manage 
      the CRYP controller events: Polling mode or Interrupt mode.

   (#) In the Polling Mode it is advised to use the following functions:
       (++) CRYP_GetFlagStatus() : to check if flags events occur. 

       -@@- The CRYPT flags do not need to be cleared since they are cleared as 
            soon as the associated event are reset.   


   (#) In the Interrupt Mode it is advised to use the following functions:
       (++) CRYP_ITConfig()       : to enable or disable the interrupt source.
       (++) CRYP_GetITStatus()    : to check if Interrupt occurs.

       -@@- The CRYPT interrupts have no pending bits, the interrupt is cleared as 
             soon as the associated event is reset. 

@endverbatim
  * @{
  */ 

/**
  * @brief  Enables or disables the specified CRYP interrupts.
  * @param  CRYP_IT: specifies the CRYP interrupt source to be enabled or disabled.
  *          This parameter can be any combination of the following values:
  *            @arg CRYP_IT_INI: Input FIFO interrupt
  *            @arg CRYP_IT_OUTI: Output FIFO interrupt
  * @param  NewState: new state of the specified CRYP interrupt.
  *           This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void CRYP_ITConfig(uint8_t CRYP_IT, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_CRYP_CONFIG_IT(CRYP_IT));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    /* Enable the selected CRYP interrupt */
    CRYP->IMSCR |= CRYP_IT;
  }
  else
  {
    /* Disable the selected CRYP interrupt */
    CRYP->IMSCR &= (uint8_t)~CRYP_IT;
  }
}

/**
  * @brief  Checks whether the specified CRYP interrupt has occurred or not.
  * @note   This function checks the status of the masked interrupt (i.e the 
  *         interrupt should be previously enabled).     
  * @param  CRYP_IT: specifies the CRYP (masked) interrupt source to check.
  *           This parameter can be one of the following values:
  *            @arg CRYP_IT_INI: Input FIFO interrupt
  *            @arg CRYP_IT_OUTI: Output FIFO interrupt
  * @retval The new state of CRYP_IT (SET or RESET).
  */
ITStatus CRYP_GetITStatus(uint8_t CRYP_IT)
{
  ITStatus bitstatus = RESET;
  /* Check the parameters */
  assert_param(IS_CRYP_GET_IT(CRYP_IT));

  /* Check the status of the specified CRYP interrupt */
  if ((CRYP->MISR &  CRYP_IT) != (uint8_t)RESET)
  {
    /* CRYP_IT is set */
    bitstatus = SET;
  }
  else
  {
    /* CRYP_IT is reset */
    bitstatus = RESET;
  }
  /* Return the CRYP_IT status */
  return bitstatus;
}

/**
  * @brief  Returns whether CRYP peripheral is enabled or disabled.
  * @param  none.
  * @retval Current state of the CRYP peripheral (ENABLE or DISABLE).
  */
FunctionalState CRYP_GetCmdStatus(void)
{
  FunctionalState state = DISABLE;

  if ((CRYP->CR & CRYP_CR_CRYPEN) != 0)
  {
    /* CRYPEN bit is set */
    state = ENABLE;
  }
  else
  {
    /* CRYPEN bit is reset */
    state = DISABLE;
  }
  return state;
}

/**
  * @brief  Checks whether the specified CRYP flag is set or not.
  * @param  CRYP_FLAG: specifies the CRYP flag to check.
  *          This parameter can be one of the following values:
  *            @arg CRYP_FLAG_IFEM: Input FIFO Empty flag.
  *            @arg CRYP_FLAG_IFNF: Input FIFO Not Full flag.
  *            @arg CRYP_FLAG_OFNE: Output FIFO Not Empty flag.
  *            @arg CRYP_FLAG_OFFU: Output FIFO Full flag.
  *            @arg CRYP_FLAG_BUSY: Busy flag.
  *            @arg CRYP_FLAG_OUTRIS: Output FIFO raw interrupt flag.
  *            @arg CRYP_FLAG_INRIS: Input FIFO raw interrupt flag.
  * @retval The new state of CRYP_FLAG (SET or RESET).
  */
FlagStatus CRYP_GetFlagStatus(uint8_t CRYP_FLAG)
{
  FlagStatus bitstatus = RESET;
  uint32_t tempreg = 0;

  /* Check the parameters */
  assert_param(IS_CRYP_GET_FLAG(CRYP_FLAG));

  /* check if the FLAG is in RISR register */
  if ((CRYP_FLAG & FLAG_MASK) != 0x00) 
  {
    tempreg = CRYP->RISR;
  }
  else  /* The FLAG is in SR register */
  {
    tempreg = CRYP->SR;
  }


  /* Check the status of the specified CRYP flag */
  if ((tempreg & CRYP_FLAG ) != (uint8_t)RESET)
  {
    /* CRYP_FLAG is set */
    bitstatus = SET;
  }
  else
  {
    /* CRYP_FLAG is reset */
    bitstatus = RESET;
  }

  /* Return the CRYP_FLAG status */
  return  bitstatus;
}

/**
  * @}
  */

/**
  * @}
  */ 

/**
  * @}
  */ 

/**
  * @}
  */ 

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/