text: /** @file
  
  OcCryptoLib
  
  Copyright (c) 2018, savvas
  
  All rights reserved.
  
  This program and the accompanying materials
  are licensed and made available under the terms and conditions of the BSD License
  which accompanies this distribution.  The full text of the license may be found at
  http://opensource.org/licenses/bsd-license.php
  
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  
  **/
  
  #ifndef OC_CRYPTO_LIB_H
  #define OC_CRYPTO_LIB_H
  
  //
  // Default to 2048-bit key length for RSA.
  //
  #ifndef CONFIG_RSA_KEY_SIZE
  #define CONFIG_RSA_KEY_SIZE 2048
  #endif
  
  //
  // Default to 128-bit key length for AES.
  //
  #ifndef CONFIG_AES_KEY_SIZE
  #define CONFIG_AES_KEY_SIZE 16
  #endif
  
  //
  // Digest sizes.
  //
  #define MD5_DIGEST_SIZE     16
  #define SHA1_DIGEST_SIZE    20
  #define SHA256_DIGEST_SIZE  32
  
  //
  // Derived parameters.
  //
  #define RSANUMBYTES ((CONFIG_RSA_KEY_SIZE) / 8)
  #define RSANUMWORDS (RSANUMBYTES / sizeof (UINT32))
  #define AES_BLOCK_SIZE 16
  
  //
  // Support all AES key sizes.
  //
  #if CONFIG_AES_KEY_SIZE == 32
  #define AES_KEY_EXP_SIZE 240
  #elif CONFIG_AES_KEY_SIZE == 24
  #define AES_KEY_EXP_SIZE 208
  #elif CONFIG_AES_KEY_SIZE == 16
  #define AES_KEY_EXP_SIZE 176
  #else
  #error "Only AES-128, AES-192, and AES-256 are supported!"
  #endif
  
  //
  // For now abort on anything but 2048, but we can support 1024 and 4096 at least.
  //
  #if CONFIG_RSA_KEY_SIZE != 2048
  #error "Only RSA-2048 is supported"
  #endif
  
  typedef struct RSA_PUBLIC_KEY_ {
    UINT32  Size;
    UINT32  N0Inv;
    UINT32  N[RSANUMWORDS];
    UINT32  Rr[RSANUMWORDS];
  } RSA_PUBLIC_KEY;
  
  typedef struct AES_CONTEXT_ {
    UINT8 RoundKey[AES_KEY_EXP_SIZE];
    UINT8 Iv[AES_BLOCK_SIZE];
  } AES_CONTEXT;
  
  typedef struct MD5_CONTEXT_ {
    UINT8   Data[64];
    UINT32  DataLen;
    UINT64  BitLen;
    UINT32  State[4];
  } MD5_CONTEXT;
  
  typedef struct SHA1_CONTEXT_ {
    UINT8   Data[64];
    UINT32  DataLen;
    UINT64  BitLen;
    UINT32  State[5];
    UINT32  K[4];
  } SHA1_CONTEXT;
  
  typedef struct SHA256_CONTEXT_ {
    UINT8   Data[64];
    UINT32  DataLen;
    UINT64  BitLen;
    UINT32  State[8];
  } SHA256_CONTEXT;
  
  //
  // Functions prototypes
  //
  BOOLEAN
  RsaVerify (
    RSA_PUBLIC_KEY  *Key,
    UINT8           *Signature,
    UINT8           *Sha256,
    UINT32          *Workbuf32
    );
  
  VOID
  AesInitCtxIv (
    AES_CONTEXT  *Context,
    CONST UINT8  *Key,
    CONST UINT8  *Iv
    );
  
  VOID
  AesSetCtxIv (
    AES_CONTEXT  *Context,
    CONST UINT8  *Iv
    );
  
  //
  // Data size MUST be mutiple of AES_BLOCK_SIZE;
  // Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
  // NOTES: you need to set Iv in Context via AesInitCtxIv() or AesSetCtxIv()
  //        no Iv should ever be reused with the same key
  //
  VOID
  AesCbcEncryptBuffer (
    AES_CONTEXT  *Context,
    UINT8        *Data,
    UINT32       Len
    );
  
  VOID
  AESCbcDecryptBuffer (
    AES_CONTEXT  *Context,
    UINT8        *Data,
    UINT32       Len
    );
  
  //
  // Same function for encrypting as for decrypting.
  // Iv is incremented for every block, and used after encryption as XOR-compliment for output
  // Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
  // NOTES: you need to set Iv in Context via AesInitCtxIv() or AesSetCtxIv()
  //        no Iv should ever be reused with the same key
  //
  VOID
  AesCtrXcryptBuffer (
    AES_CONTEXT  *Context,
    UINT8        *Data,
    UINT32       Len
    );
  
  VOID
  Md5Init (
    MD5_CONTEXT  *Context
    );
  
  VOID
  Md5Update (
    MD5_CONTEXT  *Context,
    CONST UINT8  *Data,
    UINTN        Len
    );
  
  VOID
  Md5Final (
    MD5_CONTEXT  *Context,
    UINT8        *Hash
    );
  
  VOID
  Md5 (
    UINT8  *Hash,
    UINT8  *Data,
    UINTN  Len
    );
  
  VOID
  Sha1Init (
    SHA1_CONTEXT  *Context
    );
  
  VOID
  Sha1Update (
    SHA1_CONTEXT  *Context,
    CONST UINT8   *Data,
    UINTN         Len
    );
  
  VOID
  Sha1Final (
    SHA1_CONTEXT  *Context,
    UINT8         *Hash
    );
  
  VOID
  Sha1 (
    UINT8  *Hash,
    UINT8  *Data,
    UINTN  Len
    );
  
  VOID
  Sha256Init (
    SHA256_CONTEXT  *Context
    );
  
  VOID
  Sha256Update (
    SHA256_CONTEXT  *Context,
    CONST UINT8     *Data,
    UINTN           Len
    );
  
  VOID
  Sha256Final (
    SHA256_CONTEXT  *Context,
    UINT8           *HashDigest
    );
  
  VOID
  Sha256 (
    UINT8  *Hash,
    UINT8  *Data,
    UINTN  Len
    );
  
  #endif //OC_CRYPTO_LIB_H
  