1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3  *
4  * LibTomCrypt is a library that provides various cryptographic
5  * algorithms in a highly modular and flexible manner.
6  *
7  * The library is free for all purposes without any express
8  * guarantee it works.
9  */
10 
11 /**
12    @file ocb3_init.c
13    OCB implementation, initialize state, by Tom St Denis
14 */
15 #include "tomcrypt_private.h"
16 
17 #ifdef LTC_OCB3_MODE
18 
_ocb3_int_calc_offset_zero(ocb3_state * ocb,const unsigned char * nonce,unsigned long noncelen,unsigned long taglen)19 static void _ocb3_int_calc_offset_zero(ocb3_state *ocb, const unsigned char *nonce, unsigned long noncelen, unsigned long taglen)
20 {
21    int x, y, bottom;
22    int idx, shift;
23    unsigned char iNonce[MAXBLOCKSIZE];
24    unsigned char iKtop[MAXBLOCKSIZE];
25    unsigned char iStretch[MAXBLOCKSIZE+8];
26 
27    /* Nonce = zeros(127-bitlen(N)) || 1 || N          */
28    zeromem(iNonce, sizeof(iNonce));
29    for (x = ocb->block_len-1, y=0; y<(int)noncelen; x--, y++) {
30      iNonce[x] = nonce[noncelen-y-1];
31    }
32    iNonce[x] = 0x01;
33    iNonce[0] |= ((taglen*8) % 128) << 1;
34 
35    /* bottom = str2num(Nonce[123..128])               */
36    bottom = iNonce[ocb->block_len-1] & 0x3F;
37 
38    /* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6))   */
39    iNonce[ocb->block_len-1] = iNonce[ocb->block_len-1] & 0xC0;
40    if ((cipher_descriptor[ocb->cipher]->ecb_encrypt(iNonce, iKtop, &ocb->key)) != CRYPT_OK) {
41       zeromem(ocb->Offset_current, ocb->block_len);
42       return;
43    }
44 
45    /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */
46    for (x = 0; x < ocb->block_len; x++) {
47      iStretch[x] = iKtop[x];
48    }
49    for (y = 0; y < 8; y++) {
50      iStretch[x+y] = iKtop[y] ^ iKtop[y+1];
51    }
52 
53    /* Offset_0 = Stretch[1+bottom..128+bottom]        */
54    idx = bottom / 8;
55    shift = (bottom % 8);
56    for (x = 0; x < ocb->block_len; x++) {
57       ocb->Offset_current[x] = iStretch[idx+x] << shift;
58       if (shift > 0) {
59         ocb->Offset_current[x] |= iStretch[idx+x+1] >> (8-shift);
60       }
61    }
62 }
63 
64 static const struct {
65     int           len;
66     unsigned char poly_mul[MAXBLOCKSIZE];
67 } polys[] = {
68 {
69     8,
70     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B }
71 }, {
72     16,
73     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }
75 }
76 };
77 
78 /**
79    Initialize an OCB context
80    @param ocb       [out] The destination of the OCB state
81    @param cipher    The index of the desired cipher
82    @param key       The secret key
83    @param keylen    The length of the secret key (octets)
84    @param nonce     The session nonce
85    @param noncelen  The length of the session nonce (octets, up to 15)
86    @param taglen    The length of the tag (octets, up to 16)
87    @return CRYPT_OK if successful
88 */
ocb3_init(ocb3_state * ocb,int cipher,const unsigned char * key,unsigned long keylen,const unsigned char * nonce,unsigned long noncelen,unsigned long taglen)89 int ocb3_init(ocb3_state *ocb, int cipher,
90              const unsigned char *key, unsigned long keylen,
91              const unsigned char *nonce, unsigned long noncelen,
92              unsigned long taglen)
93 {
94    int poly, x, y, m, err;
95    unsigned char *previous, *current;
96 
97    LTC_ARGCHK(ocb   != NULL);
98    LTC_ARGCHK(key   != NULL);
99    LTC_ARGCHK(nonce != NULL);
100 
101    /* valid cipher? */
102    if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
103       return err;
104    }
105    ocb->cipher = cipher;
106 
107    /* Valid Nonce?
108     * As of RFC7253: "string of no more than 120 bits" */
109    if (noncelen > (120/8)) {
110       return CRYPT_INVALID_ARG;
111    }
112 
113    /* The blockcipher must have a 128-bit blocksize */
114    if (cipher_descriptor[cipher]->block_length != 16) {
115       return CRYPT_INVALID_ARG;
116    }
117 
118    /* The TAGLEN may be any value up to 128 (bits) */
119    if (taglen > 16) {
120       return CRYPT_INVALID_ARG;
121    }
122    ocb->tag_len = taglen;
123 
124    /* determine which polys to use */
125    ocb->block_len = cipher_descriptor[cipher]->block_length;
126    x = (int)(sizeof(polys)/sizeof(polys[0]));
127    for (poly = 0; poly < x; poly++) {
128        if (polys[poly].len == ocb->block_len) {
129           break;
130        }
131    }
132    if (poly == x) {
133       return CRYPT_INVALID_ARG; /* block_len not found in polys */
134    }
135    if (polys[poly].len != ocb->block_len) {
136       return CRYPT_INVALID_ARG;
137    }
138 
139    /* schedule the key */
140    if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) {
141       return err;
142    }
143 
144    /* L_* = ENCIPHER(K, zeros(128)) */
145    zeromem(ocb->L_star, ocb->block_len);
146    if ((err = cipher_descriptor[cipher]->ecb_encrypt(ocb->L_star, ocb->L_star, &ocb->key)) != CRYPT_OK) {
147       return err;
148    }
149 
150    /* compute L_$, L_0, L_1, ... */
151    for (x = -1; x < 32; x++) {
152       if (x == -1) {                /* gonna compute: L_$ = double(L_*) */
153          current  = ocb->L_dollar;
154          previous = ocb->L_star;
155       }
156       else if (x == 0) {            /* gonna compute: L_0 = double(L_$) */
157          current  = ocb->L_[0];
158          previous = ocb->L_dollar;
159       }
160       else {                        /* gonna compute: L_i = double(L_{i-1}) for every integer i > 0 */
161          current  = ocb->L_[x];
162          previous = ocb->L_[x-1];
163       }
164       m = previous[0] >> 7;
165       for (y = 0; y < ocb->block_len-1; y++) {
166          current[y] = ((previous[y] << 1) | (previous[y+1] >> 7)) & 255;
167       }
168       current[ocb->block_len-1] = (previous[ocb->block_len-1] << 1) & 255;
169       if (m == 1) {
170          /* current[] = current[] XOR polys[poly].poly_mul[]*/
171          ocb3_int_xor_blocks(current, current, polys[poly].poly_mul, ocb->block_len);
172       }
173    }
174 
175    /* initialize ocb->Offset_current = Offset_0 */
176    _ocb3_int_calc_offset_zero(ocb, nonce, noncelen, taglen);
177 
178    /* initialize checksum to all zeros */
179    zeromem(ocb->checksum, ocb->block_len);
180 
181    /* set block index */
182    ocb->block_index = 1;
183 
184    /* initialize AAD related stuff */
185    ocb->ablock_index = 1;
186    ocb->adata_buffer_bytes = 0;
187    zeromem(ocb->aOffset_current, ocb->block_len);
188    zeromem(ocb->aSum_current, ocb->block_len);
189 
190    return CRYPT_OK;
191 }
192 
193 #endif
194 
195 /* ref:         $Format:%D$ */
196 /* git commit:  $Format:%H$ */
197 /* commit time: $Format:%ai$ */
198