1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 
4 /**
5    @file ocb_init.c
6    OCB implementation, initialize state, by Tom St Denis
7 */
8 #include "tomcrypt_private.h"
9 
10 #ifdef LTC_OCB_MODE
11 
12 static const struct {
13     int           len;
14     unsigned char poly_div[MAXBLOCKSIZE],
15                   poly_mul[MAXBLOCKSIZE];
16 } polys[] = {
17 {
18     8,
19     { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D },
20     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B }
21 }, {
22     16,
23     { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 },
25     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }
27 }
28 };
29 
30 /**
31   Initialize an OCB context.
32   @param ocb     [out] The destination of the OCB state
33   @param cipher  The index of the desired cipher
34   @param key     The secret key
35   @param keylen  The length of the secret key (octets)
36   @param nonce   The session nonce (length of the block size of the cipher)
37   @return CRYPT_OK if successful
38 */
ocb_init(ocb_state * ocb,int cipher,const unsigned char * key,unsigned long keylen,const unsigned char * nonce)39 int ocb_init(ocb_state *ocb, int cipher,
40              const unsigned char *key, unsigned long keylen, const unsigned char *nonce)
41 {
42    int poly, x, y, m, err;
43 
44    LTC_ARGCHK(ocb   != NULL);
45    LTC_ARGCHK(key   != NULL);
46    LTC_ARGCHK(nonce != NULL);
47 
48    /* valid cipher? */
49    if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
50       return err;
51    }
52 
53    /* determine which polys to use */
54    ocb->block_len = cipher_descriptor[cipher]->block_length;
55    x = (int)(sizeof(polys)/sizeof(polys[0]));
56    for (poly = 0; poly < x; poly++) {
57        if (polys[poly].len == ocb->block_len) {
58           break;
59        }
60    }
61    if (poly == x) {
62       return CRYPT_INVALID_ARG; /* block_len not found in polys */
63    }
64    if (polys[poly].len != ocb->block_len) {
65       return CRYPT_INVALID_ARG;
66    }
67 
68    /* schedule the key */
69    if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) {
70       return err;
71    }
72 
73    /* find L = E[0] */
74    zeromem(ocb->L, ocb->block_len);
75    if ((err = cipher_descriptor[cipher]->ecb_encrypt(ocb->L, ocb->L, &ocb->key)) != CRYPT_OK) {
76       return err;
77    }
78 
79    /* find R = E[N xor L] */
80    for (x = 0; x < ocb->block_len; x++) {
81        ocb->R[x] = ocb->L[x] ^ nonce[x];
82    }
83    if ((err = cipher_descriptor[cipher]->ecb_encrypt(ocb->R, ocb->R, &ocb->key)) != CRYPT_OK) {
84       return err;
85    }
86 
87    /* find Ls[i] = L << i for i == 0..31 */
88    XMEMCPY(ocb->Ls[0], ocb->L, ocb->block_len);
89    for (x = 1; x < 32; x++) {
90        m = ocb->Ls[x-1][0] >> 7;
91        for (y = 0; y < ocb->block_len-1; y++) {
92            ocb->Ls[x][y] = ((ocb->Ls[x-1][y] << 1) | (ocb->Ls[x-1][y+1] >> 7)) & 255;
93        }
94        ocb->Ls[x][ocb->block_len-1] = (ocb->Ls[x-1][ocb->block_len-1] << 1) & 255;
95 
96        if (m == 1) {
97           for (y = 0; y < ocb->block_len; y++) {
98               ocb->Ls[x][y] ^= polys[poly].poly_mul[y];
99           }
100        }
101    }
102 
103    /* find Lr = L / x */
104    m = ocb->L[ocb->block_len-1] & 1;
105 
106    /* shift right */
107    for (x = ocb->block_len - 1; x > 0; x--) {
108       ocb->Lr[x] = ((ocb->L[x] >> 1) | (ocb->L[x-1] << 7)) & 255;
109    }
110    ocb->Lr[0] = ocb->L[0] >> 1;
111 
112    if (m == 1) {
113       for (x = 0; x < ocb->block_len; x++) {
114          ocb->Lr[x] ^= polys[poly].poly_div[x];
115       }
116    }
117 
118    /* set Li, checksum */
119    zeromem(ocb->Li,       ocb->block_len);
120    zeromem(ocb->checksum, ocb->block_len);
121 
122    /* set other params */
123    ocb->block_index = 1;
124    ocb->cipher      = cipher;
125 
126    return CRYPT_OK;
127 }
128 
129 #endif
130