11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include <string.h> 111cb0ef41Sopenharmony_ci#include <openssl/crypto.h> 121cb0ef41Sopenharmony_ci#include <openssl/err.h> 131cb0ef41Sopenharmony_ci#include "crypto/modes.h" 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_OCB 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ci/* 181cb0ef41Sopenharmony_ci * Calculate the number of binary trailing zero's in any given number 191cb0ef41Sopenharmony_ci */ 201cb0ef41Sopenharmony_cistatic u32 ocb_ntz(u64 n) 211cb0ef41Sopenharmony_ci{ 221cb0ef41Sopenharmony_ci u32 cnt = 0; 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci /* 251cb0ef41Sopenharmony_ci * We do a right-to-left simple sequential search. This is surprisingly 261cb0ef41Sopenharmony_ci * efficient as the distribution of trailing zeros is not uniform, 271cb0ef41Sopenharmony_ci * e.g. the number of possible inputs with no trailing zeros is equal to 281cb0ef41Sopenharmony_ci * the number with 1 or more; the number with exactly 1 is equal to the 291cb0ef41Sopenharmony_ci * number with 2 or more, etc. Checking the last two bits covers 75% of 301cb0ef41Sopenharmony_ci * all numbers. Checking the last three covers 87.5% 311cb0ef41Sopenharmony_ci */ 321cb0ef41Sopenharmony_ci while (!(n & 1)) { 331cb0ef41Sopenharmony_ci n >>= 1; 341cb0ef41Sopenharmony_ci cnt++; 351cb0ef41Sopenharmony_ci } 361cb0ef41Sopenharmony_ci return cnt; 371cb0ef41Sopenharmony_ci} 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci/* 401cb0ef41Sopenharmony_ci * Shift a block of 16 bytes left by shift bits 411cb0ef41Sopenharmony_ci */ 421cb0ef41Sopenharmony_cistatic void ocb_block_lshift(const unsigned char *in, size_t shift, 431cb0ef41Sopenharmony_ci unsigned char *out) 441cb0ef41Sopenharmony_ci{ 451cb0ef41Sopenharmony_ci int i; 461cb0ef41Sopenharmony_ci unsigned char carry = 0, carry_next; 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci for (i = 15; i >= 0; i--) { 491cb0ef41Sopenharmony_ci carry_next = in[i] >> (8 - shift); 501cb0ef41Sopenharmony_ci out[i] = (in[i] << shift) | carry; 511cb0ef41Sopenharmony_ci carry = carry_next; 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci} 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci/* 561cb0ef41Sopenharmony_ci * Perform a "double" operation as per OCB spec 571cb0ef41Sopenharmony_ci */ 581cb0ef41Sopenharmony_cistatic void ocb_double(OCB_BLOCK *in, OCB_BLOCK *out) 591cb0ef41Sopenharmony_ci{ 601cb0ef41Sopenharmony_ci unsigned char mask; 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci /* 631cb0ef41Sopenharmony_ci * Calculate the mask based on the most significant bit. There are more 641cb0ef41Sopenharmony_ci * efficient ways to do this - but this way is constant time 651cb0ef41Sopenharmony_ci */ 661cb0ef41Sopenharmony_ci mask = in->c[0] & 0x80; 671cb0ef41Sopenharmony_ci mask >>= 7; 681cb0ef41Sopenharmony_ci mask = (0 - mask) & 0x87; 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci ocb_block_lshift(in->c, 1, out->c); 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci out->c[15] ^= mask; 731cb0ef41Sopenharmony_ci} 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci/* 761cb0ef41Sopenharmony_ci * Perform an xor on in1 and in2 - each of len bytes. Store result in out 771cb0ef41Sopenharmony_ci */ 781cb0ef41Sopenharmony_cistatic void ocb_block_xor(const unsigned char *in1, 791cb0ef41Sopenharmony_ci const unsigned char *in2, size_t len, 801cb0ef41Sopenharmony_ci unsigned char *out) 811cb0ef41Sopenharmony_ci{ 821cb0ef41Sopenharmony_ci size_t i; 831cb0ef41Sopenharmony_ci for (i = 0; i < len; i++) { 841cb0ef41Sopenharmony_ci out[i] = in1[i] ^ in2[i]; 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci} 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci/* 891cb0ef41Sopenharmony_ci * Lookup L_index in our lookup table. If we haven't already got it we need to 901cb0ef41Sopenharmony_ci * calculate it 911cb0ef41Sopenharmony_ci */ 921cb0ef41Sopenharmony_cistatic OCB_BLOCK *ocb_lookup_l(OCB128_CONTEXT *ctx, size_t idx) 931cb0ef41Sopenharmony_ci{ 941cb0ef41Sopenharmony_ci size_t l_index = ctx->l_index; 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci if (idx <= l_index) { 971cb0ef41Sopenharmony_ci return ctx->l + idx; 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci /* We don't have it - so calculate it */ 1011cb0ef41Sopenharmony_ci if (idx >= ctx->max_l_index) { 1021cb0ef41Sopenharmony_ci void *tmp_ptr; 1031cb0ef41Sopenharmony_ci /* 1041cb0ef41Sopenharmony_ci * Each additional entry allows to process almost double as 1051cb0ef41Sopenharmony_ci * much data, so that in linear world the table will need to 1061cb0ef41Sopenharmony_ci * be expanded with smaller and smaller increments. Originally 1071cb0ef41Sopenharmony_ci * it was doubling in size, which was a waste. Growing it 1081cb0ef41Sopenharmony_ci * linearly is not formally optimal, but is simpler to implement. 1091cb0ef41Sopenharmony_ci * We grow table by minimally required 4*n that would accommodate 1101cb0ef41Sopenharmony_ci * the index. 1111cb0ef41Sopenharmony_ci */ 1121cb0ef41Sopenharmony_ci ctx->max_l_index += (idx - ctx->max_l_index + 4) & ~3; 1131cb0ef41Sopenharmony_ci tmp_ptr = OPENSSL_realloc(ctx->l, ctx->max_l_index * sizeof(OCB_BLOCK)); 1141cb0ef41Sopenharmony_ci if (tmp_ptr == NULL) /* prevent ctx->l from being clobbered */ 1151cb0ef41Sopenharmony_ci return NULL; 1161cb0ef41Sopenharmony_ci ctx->l = tmp_ptr; 1171cb0ef41Sopenharmony_ci } 1181cb0ef41Sopenharmony_ci while (l_index < idx) { 1191cb0ef41Sopenharmony_ci ocb_double(ctx->l + l_index, ctx->l + l_index + 1); 1201cb0ef41Sopenharmony_ci l_index++; 1211cb0ef41Sopenharmony_ci } 1221cb0ef41Sopenharmony_ci ctx->l_index = l_index; 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci return ctx->l + idx; 1251cb0ef41Sopenharmony_ci} 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci/* 1281cb0ef41Sopenharmony_ci * Create a new OCB128_CONTEXT 1291cb0ef41Sopenharmony_ci */ 1301cb0ef41Sopenharmony_ciOCB128_CONTEXT *CRYPTO_ocb128_new(void *keyenc, void *keydec, 1311cb0ef41Sopenharmony_ci block128_f encrypt, block128_f decrypt, 1321cb0ef41Sopenharmony_ci ocb128_f stream) 1331cb0ef41Sopenharmony_ci{ 1341cb0ef41Sopenharmony_ci OCB128_CONTEXT *octx; 1351cb0ef41Sopenharmony_ci int ret; 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci if ((octx = OPENSSL_malloc(sizeof(*octx))) != NULL) { 1381cb0ef41Sopenharmony_ci ret = CRYPTO_ocb128_init(octx, keyenc, keydec, encrypt, decrypt, 1391cb0ef41Sopenharmony_ci stream); 1401cb0ef41Sopenharmony_ci if (ret) 1411cb0ef41Sopenharmony_ci return octx; 1421cb0ef41Sopenharmony_ci OPENSSL_free(octx); 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci return NULL; 1461cb0ef41Sopenharmony_ci} 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci/* 1491cb0ef41Sopenharmony_ci * Initialise an existing OCB128_CONTEXT 1501cb0ef41Sopenharmony_ci */ 1511cb0ef41Sopenharmony_ciint CRYPTO_ocb128_init(OCB128_CONTEXT *ctx, void *keyenc, void *keydec, 1521cb0ef41Sopenharmony_ci block128_f encrypt, block128_f decrypt, 1531cb0ef41Sopenharmony_ci ocb128_f stream) 1541cb0ef41Sopenharmony_ci{ 1551cb0ef41Sopenharmony_ci memset(ctx, 0, sizeof(*ctx)); 1561cb0ef41Sopenharmony_ci ctx->l_index = 0; 1571cb0ef41Sopenharmony_ci ctx->max_l_index = 5; 1581cb0ef41Sopenharmony_ci if ((ctx->l = OPENSSL_malloc(ctx->max_l_index * 16)) == NULL) { 1591cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 1601cb0ef41Sopenharmony_ci return 0; 1611cb0ef41Sopenharmony_ci } 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci /* 1641cb0ef41Sopenharmony_ci * We set both the encryption and decryption key schedules - decryption 1651cb0ef41Sopenharmony_ci * needs both. Don't really need decryption schedule if only doing 1661cb0ef41Sopenharmony_ci * encryption - but it simplifies things to take it anyway 1671cb0ef41Sopenharmony_ci */ 1681cb0ef41Sopenharmony_ci ctx->encrypt = encrypt; 1691cb0ef41Sopenharmony_ci ctx->decrypt = decrypt; 1701cb0ef41Sopenharmony_ci ctx->stream = stream; 1711cb0ef41Sopenharmony_ci ctx->keyenc = keyenc; 1721cb0ef41Sopenharmony_ci ctx->keydec = keydec; 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci /* L_* = ENCIPHER(K, zeros(128)) */ 1751cb0ef41Sopenharmony_ci ctx->encrypt(ctx->l_star.c, ctx->l_star.c, ctx->keyenc); 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci /* L_$ = double(L_*) */ 1781cb0ef41Sopenharmony_ci ocb_double(&ctx->l_star, &ctx->l_dollar); 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci /* L_0 = double(L_$) */ 1811cb0ef41Sopenharmony_ci ocb_double(&ctx->l_dollar, ctx->l); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci /* L_{i} = double(L_{i-1}) */ 1841cb0ef41Sopenharmony_ci ocb_double(ctx->l, ctx->l+1); 1851cb0ef41Sopenharmony_ci ocb_double(ctx->l+1, ctx->l+2); 1861cb0ef41Sopenharmony_ci ocb_double(ctx->l+2, ctx->l+3); 1871cb0ef41Sopenharmony_ci ocb_double(ctx->l+3, ctx->l+4); 1881cb0ef41Sopenharmony_ci ctx->l_index = 4; /* enough to process up to 496 bytes */ 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci return 1; 1911cb0ef41Sopenharmony_ci} 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci/* 1941cb0ef41Sopenharmony_ci * Copy an OCB128_CONTEXT object 1951cb0ef41Sopenharmony_ci */ 1961cb0ef41Sopenharmony_ciint CRYPTO_ocb128_copy_ctx(OCB128_CONTEXT *dest, OCB128_CONTEXT *src, 1971cb0ef41Sopenharmony_ci void *keyenc, void *keydec) 1981cb0ef41Sopenharmony_ci{ 1991cb0ef41Sopenharmony_ci memcpy(dest, src, sizeof(OCB128_CONTEXT)); 2001cb0ef41Sopenharmony_ci if (keyenc) 2011cb0ef41Sopenharmony_ci dest->keyenc = keyenc; 2021cb0ef41Sopenharmony_ci if (keydec) 2031cb0ef41Sopenharmony_ci dest->keydec = keydec; 2041cb0ef41Sopenharmony_ci if (src->l) { 2051cb0ef41Sopenharmony_ci if ((dest->l = OPENSSL_malloc(src->max_l_index * 16)) == NULL) { 2061cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 2071cb0ef41Sopenharmony_ci return 0; 2081cb0ef41Sopenharmony_ci } 2091cb0ef41Sopenharmony_ci memcpy(dest->l, src->l, (src->l_index + 1) * 16); 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci return 1; 2121cb0ef41Sopenharmony_ci} 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci/* 2151cb0ef41Sopenharmony_ci * Set the IV to be used for this operation. Must be 1 - 15 bytes. 2161cb0ef41Sopenharmony_ci */ 2171cb0ef41Sopenharmony_ciint CRYPTO_ocb128_setiv(OCB128_CONTEXT *ctx, const unsigned char *iv, 2181cb0ef41Sopenharmony_ci size_t len, size_t taglen) 2191cb0ef41Sopenharmony_ci{ 2201cb0ef41Sopenharmony_ci unsigned char ktop[16], tmp[16], mask; 2211cb0ef41Sopenharmony_ci unsigned char stretch[24], nonce[16]; 2221cb0ef41Sopenharmony_ci size_t bottom, shift; 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci /* 2251cb0ef41Sopenharmony_ci * Spec says IV is 120 bits or fewer - it allows non byte aligned lengths. 2261cb0ef41Sopenharmony_ci * We don't support this at this stage 2271cb0ef41Sopenharmony_ci */ 2281cb0ef41Sopenharmony_ci if ((len > 15) || (len < 1) || (taglen > 16) || (taglen < 1)) { 2291cb0ef41Sopenharmony_ci return -1; 2301cb0ef41Sopenharmony_ci } 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci /* Reset nonce-dependent variables */ 2331cb0ef41Sopenharmony_ci memset(&ctx->sess, 0, sizeof(ctx->sess)); 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci /* Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N */ 2361cb0ef41Sopenharmony_ci nonce[0] = ((taglen * 8) % 128) << 1; 2371cb0ef41Sopenharmony_ci memset(nonce + 1, 0, 15); 2381cb0ef41Sopenharmony_ci memcpy(nonce + 16 - len, iv, len); 2391cb0ef41Sopenharmony_ci nonce[15 - len] |= 1; 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci /* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) */ 2421cb0ef41Sopenharmony_ci memcpy(tmp, nonce, 16); 2431cb0ef41Sopenharmony_ci tmp[15] &= 0xc0; 2441cb0ef41Sopenharmony_ci ctx->encrypt(tmp, ktop, ctx->keyenc); 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */ 2471cb0ef41Sopenharmony_ci memcpy(stretch, ktop, 16); 2481cb0ef41Sopenharmony_ci ocb_block_xor(ktop, ktop + 1, 8, stretch + 16); 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci /* bottom = str2num(Nonce[123..128]) */ 2511cb0ef41Sopenharmony_ci bottom = nonce[15] & 0x3f; 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci /* Offset_0 = Stretch[1+bottom..128+bottom] */ 2541cb0ef41Sopenharmony_ci shift = bottom % 8; 2551cb0ef41Sopenharmony_ci ocb_block_lshift(stretch + (bottom / 8), shift, ctx->sess.offset.c); 2561cb0ef41Sopenharmony_ci mask = 0xff; 2571cb0ef41Sopenharmony_ci mask <<= 8 - shift; 2581cb0ef41Sopenharmony_ci ctx->sess.offset.c[15] |= 2591cb0ef41Sopenharmony_ci (*(stretch + (bottom / 8) + 16) & mask) >> (8 - shift); 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci return 1; 2621cb0ef41Sopenharmony_ci} 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci/* 2651cb0ef41Sopenharmony_ci * Provide any AAD. This can be called multiple times. Only the final time can 2661cb0ef41Sopenharmony_ci * have a partial block 2671cb0ef41Sopenharmony_ci */ 2681cb0ef41Sopenharmony_ciint CRYPTO_ocb128_aad(OCB128_CONTEXT *ctx, const unsigned char *aad, 2691cb0ef41Sopenharmony_ci size_t len) 2701cb0ef41Sopenharmony_ci{ 2711cb0ef41Sopenharmony_ci u64 i, all_num_blocks; 2721cb0ef41Sopenharmony_ci size_t num_blocks, last_len; 2731cb0ef41Sopenharmony_ci OCB_BLOCK tmp; 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci /* Calculate the number of blocks of AAD provided now, and so far */ 2761cb0ef41Sopenharmony_ci num_blocks = len / 16; 2771cb0ef41Sopenharmony_ci all_num_blocks = num_blocks + ctx->sess.blocks_hashed; 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci /* Loop through all full blocks of AAD */ 2801cb0ef41Sopenharmony_ci for (i = ctx->sess.blocks_hashed + 1; i <= all_num_blocks; i++) { 2811cb0ef41Sopenharmony_ci OCB_BLOCK *lookup; 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ 2841cb0ef41Sopenharmony_ci lookup = ocb_lookup_l(ctx, ocb_ntz(i)); 2851cb0ef41Sopenharmony_ci if (lookup == NULL) 2861cb0ef41Sopenharmony_ci return 0; 2871cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset_aad, lookup, &ctx->sess.offset_aad); 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci memcpy(tmp.c, aad, 16); 2901cb0ef41Sopenharmony_ci aad += 16; 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ 2931cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset_aad, &tmp, &tmp); 2941cb0ef41Sopenharmony_ci ctx->encrypt(tmp.c, tmp.c, ctx->keyenc); 2951cb0ef41Sopenharmony_ci ocb_block16_xor(&tmp, &ctx->sess.sum, &ctx->sess.sum); 2961cb0ef41Sopenharmony_ci } 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci /* 2991cb0ef41Sopenharmony_ci * Check if we have any partial blocks left over. This is only valid in the 3001cb0ef41Sopenharmony_ci * last call to this function 3011cb0ef41Sopenharmony_ci */ 3021cb0ef41Sopenharmony_ci last_len = len % 16; 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci if (last_len > 0) { 3051cb0ef41Sopenharmony_ci /* Offset_* = Offset_m xor L_* */ 3061cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset_aad, &ctx->l_star, 3071cb0ef41Sopenharmony_ci &ctx->sess.offset_aad); 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */ 3101cb0ef41Sopenharmony_ci memset(tmp.c, 0, 16); 3111cb0ef41Sopenharmony_ci memcpy(tmp.c, aad, last_len); 3121cb0ef41Sopenharmony_ci tmp.c[last_len] = 0x80; 3131cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset_aad, &tmp, &tmp); 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */ 3161cb0ef41Sopenharmony_ci ctx->encrypt(tmp.c, tmp.c, ctx->keyenc); 3171cb0ef41Sopenharmony_ci ocb_block16_xor(&tmp, &ctx->sess.sum, &ctx->sess.sum); 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci ctx->sess.blocks_hashed = all_num_blocks; 3211cb0ef41Sopenharmony_ci 3221cb0ef41Sopenharmony_ci return 1; 3231cb0ef41Sopenharmony_ci} 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci/* 3261cb0ef41Sopenharmony_ci * Provide any data to be encrypted. This can be called multiple times. Only 3271cb0ef41Sopenharmony_ci * the final time can have a partial block 3281cb0ef41Sopenharmony_ci */ 3291cb0ef41Sopenharmony_ciint CRYPTO_ocb128_encrypt(OCB128_CONTEXT *ctx, 3301cb0ef41Sopenharmony_ci const unsigned char *in, unsigned char *out, 3311cb0ef41Sopenharmony_ci size_t len) 3321cb0ef41Sopenharmony_ci{ 3331cb0ef41Sopenharmony_ci u64 i, all_num_blocks; 3341cb0ef41Sopenharmony_ci size_t num_blocks, last_len; 3351cb0ef41Sopenharmony_ci 3361cb0ef41Sopenharmony_ci /* 3371cb0ef41Sopenharmony_ci * Calculate the number of blocks of data to be encrypted provided now, and 3381cb0ef41Sopenharmony_ci * so far 3391cb0ef41Sopenharmony_ci */ 3401cb0ef41Sopenharmony_ci num_blocks = len / 16; 3411cb0ef41Sopenharmony_ci all_num_blocks = num_blocks + ctx->sess.blocks_processed; 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ci if (num_blocks && all_num_blocks == (size_t)all_num_blocks 3441cb0ef41Sopenharmony_ci && ctx->stream != NULL) { 3451cb0ef41Sopenharmony_ci size_t max_idx = 0, top = (size_t)all_num_blocks; 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_ci /* 3481cb0ef41Sopenharmony_ci * See how many L_{i} entries we need to process data at hand 3491cb0ef41Sopenharmony_ci * and pre-compute missing entries in the table [if any]... 3501cb0ef41Sopenharmony_ci */ 3511cb0ef41Sopenharmony_ci while (top >>= 1) 3521cb0ef41Sopenharmony_ci max_idx++; 3531cb0ef41Sopenharmony_ci if (ocb_lookup_l(ctx, max_idx) == NULL) 3541cb0ef41Sopenharmony_ci return 0; 3551cb0ef41Sopenharmony_ci 3561cb0ef41Sopenharmony_ci ctx->stream(in, out, num_blocks, ctx->keyenc, 3571cb0ef41Sopenharmony_ci (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, 3581cb0ef41Sopenharmony_ci (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); 3591cb0ef41Sopenharmony_ci } else { 3601cb0ef41Sopenharmony_ci /* Loop through all full blocks to be encrypted */ 3611cb0ef41Sopenharmony_ci for (i = ctx->sess.blocks_processed + 1; i <= all_num_blocks; i++) { 3621cb0ef41Sopenharmony_ci OCB_BLOCK *lookup; 3631cb0ef41Sopenharmony_ci OCB_BLOCK tmp; 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ 3661cb0ef41Sopenharmony_ci lookup = ocb_lookup_l(ctx, ocb_ntz(i)); 3671cb0ef41Sopenharmony_ci if (lookup == NULL) 3681cb0ef41Sopenharmony_ci return 0; 3691cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset, lookup, &ctx->sess.offset); 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci memcpy(tmp.c, in, 16); 3721cb0ef41Sopenharmony_ci in += 16; 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci /* Checksum_i = Checksum_{i-1} xor P_i */ 3751cb0ef41Sopenharmony_ci ocb_block16_xor(&tmp, &ctx->sess.checksum, &ctx->sess.checksum); 3761cb0ef41Sopenharmony_ci 3771cb0ef41Sopenharmony_ci /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ 3781cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset, &tmp, &tmp); 3791cb0ef41Sopenharmony_ci ctx->encrypt(tmp.c, tmp.c, ctx->keyenc); 3801cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset, &tmp, &tmp); 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci memcpy(out, tmp.c, 16); 3831cb0ef41Sopenharmony_ci out += 16; 3841cb0ef41Sopenharmony_ci } 3851cb0ef41Sopenharmony_ci } 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci /* 3881cb0ef41Sopenharmony_ci * Check if we have any partial blocks left over. This is only valid in the 3891cb0ef41Sopenharmony_ci * last call to this function 3901cb0ef41Sopenharmony_ci */ 3911cb0ef41Sopenharmony_ci last_len = len % 16; 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ci if (last_len > 0) { 3941cb0ef41Sopenharmony_ci OCB_BLOCK pad; 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci /* Offset_* = Offset_m xor L_* */ 3971cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset, &ctx->l_star, &ctx->sess.offset); 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci /* Pad = ENCIPHER(K, Offset_*) */ 4001cb0ef41Sopenharmony_ci ctx->encrypt(ctx->sess.offset.c, pad.c, ctx->keyenc); 4011cb0ef41Sopenharmony_ci 4021cb0ef41Sopenharmony_ci /* C_* = P_* xor Pad[1..bitlen(P_*)] */ 4031cb0ef41Sopenharmony_ci ocb_block_xor(in, pad.c, last_len, out); 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ 4061cb0ef41Sopenharmony_ci memset(pad.c, 0, 16); /* borrow pad */ 4071cb0ef41Sopenharmony_ci memcpy(pad.c, in, last_len); 4081cb0ef41Sopenharmony_ci pad.c[last_len] = 0x80; 4091cb0ef41Sopenharmony_ci ocb_block16_xor(&pad, &ctx->sess.checksum, &ctx->sess.checksum); 4101cb0ef41Sopenharmony_ci } 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ci ctx->sess.blocks_processed = all_num_blocks; 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ci return 1; 4151cb0ef41Sopenharmony_ci} 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_ci/* 4181cb0ef41Sopenharmony_ci * Provide any data to be decrypted. This can be called multiple times. Only 4191cb0ef41Sopenharmony_ci * the final time can have a partial block 4201cb0ef41Sopenharmony_ci */ 4211cb0ef41Sopenharmony_ciint CRYPTO_ocb128_decrypt(OCB128_CONTEXT *ctx, 4221cb0ef41Sopenharmony_ci const unsigned char *in, unsigned char *out, 4231cb0ef41Sopenharmony_ci size_t len) 4241cb0ef41Sopenharmony_ci{ 4251cb0ef41Sopenharmony_ci u64 i, all_num_blocks; 4261cb0ef41Sopenharmony_ci size_t num_blocks, last_len; 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ci /* 4291cb0ef41Sopenharmony_ci * Calculate the number of blocks of data to be decrypted provided now, and 4301cb0ef41Sopenharmony_ci * so far 4311cb0ef41Sopenharmony_ci */ 4321cb0ef41Sopenharmony_ci num_blocks = len / 16; 4331cb0ef41Sopenharmony_ci all_num_blocks = num_blocks + ctx->sess.blocks_processed; 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_ci if (num_blocks && all_num_blocks == (size_t)all_num_blocks 4361cb0ef41Sopenharmony_ci && ctx->stream != NULL) { 4371cb0ef41Sopenharmony_ci size_t max_idx = 0, top = (size_t)all_num_blocks; 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_ci /* 4401cb0ef41Sopenharmony_ci * See how many L_{i} entries we need to process data at hand 4411cb0ef41Sopenharmony_ci * and pre-compute missing entries in the table [if any]... 4421cb0ef41Sopenharmony_ci */ 4431cb0ef41Sopenharmony_ci while (top >>= 1) 4441cb0ef41Sopenharmony_ci max_idx++; 4451cb0ef41Sopenharmony_ci if (ocb_lookup_l(ctx, max_idx) == NULL) 4461cb0ef41Sopenharmony_ci return 0; 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ci ctx->stream(in, out, num_blocks, ctx->keydec, 4491cb0ef41Sopenharmony_ci (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, 4501cb0ef41Sopenharmony_ci (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); 4511cb0ef41Sopenharmony_ci } else { 4521cb0ef41Sopenharmony_ci OCB_BLOCK tmp; 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_ci /* Loop through all full blocks to be decrypted */ 4551cb0ef41Sopenharmony_ci for (i = ctx->sess.blocks_processed + 1; i <= all_num_blocks; i++) { 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_ci /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ 4581cb0ef41Sopenharmony_ci OCB_BLOCK *lookup = ocb_lookup_l(ctx, ocb_ntz(i)); 4591cb0ef41Sopenharmony_ci if (lookup == NULL) 4601cb0ef41Sopenharmony_ci return 0; 4611cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset, lookup, &ctx->sess.offset); 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_ci memcpy(tmp.c, in, 16); 4641cb0ef41Sopenharmony_ci in += 16; 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_ci /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */ 4671cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset, &tmp, &tmp); 4681cb0ef41Sopenharmony_ci ctx->decrypt(tmp.c, tmp.c, ctx->keydec); 4691cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset, &tmp, &tmp); 4701cb0ef41Sopenharmony_ci 4711cb0ef41Sopenharmony_ci /* Checksum_i = Checksum_{i-1} xor P_i */ 4721cb0ef41Sopenharmony_ci ocb_block16_xor(&tmp, &ctx->sess.checksum, &ctx->sess.checksum); 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci memcpy(out, tmp.c, 16); 4751cb0ef41Sopenharmony_ci out += 16; 4761cb0ef41Sopenharmony_ci } 4771cb0ef41Sopenharmony_ci } 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci /* 4801cb0ef41Sopenharmony_ci * Check if we have any partial blocks left over. This is only valid in the 4811cb0ef41Sopenharmony_ci * last call to this function 4821cb0ef41Sopenharmony_ci */ 4831cb0ef41Sopenharmony_ci last_len = len % 16; 4841cb0ef41Sopenharmony_ci 4851cb0ef41Sopenharmony_ci if (last_len > 0) { 4861cb0ef41Sopenharmony_ci OCB_BLOCK pad; 4871cb0ef41Sopenharmony_ci 4881cb0ef41Sopenharmony_ci /* Offset_* = Offset_m xor L_* */ 4891cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.offset, &ctx->l_star, &ctx->sess.offset); 4901cb0ef41Sopenharmony_ci 4911cb0ef41Sopenharmony_ci /* Pad = ENCIPHER(K, Offset_*) */ 4921cb0ef41Sopenharmony_ci ctx->encrypt(ctx->sess.offset.c, pad.c, ctx->keyenc); 4931cb0ef41Sopenharmony_ci 4941cb0ef41Sopenharmony_ci /* P_* = C_* xor Pad[1..bitlen(C_*)] */ 4951cb0ef41Sopenharmony_ci ocb_block_xor(in, pad.c, last_len, out); 4961cb0ef41Sopenharmony_ci 4971cb0ef41Sopenharmony_ci /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ 4981cb0ef41Sopenharmony_ci memset(pad.c, 0, 16); /* borrow pad */ 4991cb0ef41Sopenharmony_ci memcpy(pad.c, out, last_len); 5001cb0ef41Sopenharmony_ci pad.c[last_len] = 0x80; 5011cb0ef41Sopenharmony_ci ocb_block16_xor(&pad, &ctx->sess.checksum, &ctx->sess.checksum); 5021cb0ef41Sopenharmony_ci } 5031cb0ef41Sopenharmony_ci 5041cb0ef41Sopenharmony_ci ctx->sess.blocks_processed = all_num_blocks; 5051cb0ef41Sopenharmony_ci 5061cb0ef41Sopenharmony_ci return 1; 5071cb0ef41Sopenharmony_ci} 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_cistatic int ocb_finish(OCB128_CONTEXT *ctx, unsigned char *tag, size_t len, 5101cb0ef41Sopenharmony_ci int write) 5111cb0ef41Sopenharmony_ci{ 5121cb0ef41Sopenharmony_ci OCB_BLOCK tmp; 5131cb0ef41Sopenharmony_ci 5141cb0ef41Sopenharmony_ci if (len > 16 || len < 1) { 5151cb0ef41Sopenharmony_ci return -1; 5161cb0ef41Sopenharmony_ci } 5171cb0ef41Sopenharmony_ci 5181cb0ef41Sopenharmony_ci /* 5191cb0ef41Sopenharmony_ci * Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) 5201cb0ef41Sopenharmony_ci */ 5211cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->sess.checksum, &ctx->sess.offset, &tmp); 5221cb0ef41Sopenharmony_ci ocb_block16_xor(&ctx->l_dollar, &tmp, &tmp); 5231cb0ef41Sopenharmony_ci ctx->encrypt(tmp.c, tmp.c, ctx->keyenc); 5241cb0ef41Sopenharmony_ci ocb_block16_xor(&tmp, &ctx->sess.sum, &tmp); 5251cb0ef41Sopenharmony_ci 5261cb0ef41Sopenharmony_ci if (write) { 5271cb0ef41Sopenharmony_ci memcpy(tag, &tmp, len); 5281cb0ef41Sopenharmony_ci return 1; 5291cb0ef41Sopenharmony_ci } else { 5301cb0ef41Sopenharmony_ci return CRYPTO_memcmp(&tmp, tag, len); 5311cb0ef41Sopenharmony_ci } 5321cb0ef41Sopenharmony_ci} 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ci/* 5351cb0ef41Sopenharmony_ci * Calculate the tag and verify it against the supplied tag 5361cb0ef41Sopenharmony_ci */ 5371cb0ef41Sopenharmony_ciint CRYPTO_ocb128_finish(OCB128_CONTEXT *ctx, const unsigned char *tag, 5381cb0ef41Sopenharmony_ci size_t len) 5391cb0ef41Sopenharmony_ci{ 5401cb0ef41Sopenharmony_ci return ocb_finish(ctx, (unsigned char*)tag, len, 0); 5411cb0ef41Sopenharmony_ci} 5421cb0ef41Sopenharmony_ci 5431cb0ef41Sopenharmony_ci/* 5441cb0ef41Sopenharmony_ci * Retrieve the calculated tag 5451cb0ef41Sopenharmony_ci */ 5461cb0ef41Sopenharmony_ciint CRYPTO_ocb128_tag(OCB128_CONTEXT *ctx, unsigned char *tag, size_t len) 5471cb0ef41Sopenharmony_ci{ 5481cb0ef41Sopenharmony_ci return ocb_finish(ctx, tag, len, 1); 5491cb0ef41Sopenharmony_ci} 5501cb0ef41Sopenharmony_ci 5511cb0ef41Sopenharmony_ci/* 5521cb0ef41Sopenharmony_ci * Release all resources 5531cb0ef41Sopenharmony_ci */ 5541cb0ef41Sopenharmony_civoid CRYPTO_ocb128_cleanup(OCB128_CONTEXT *ctx) 5551cb0ef41Sopenharmony_ci{ 5561cb0ef41Sopenharmony_ci if (ctx) { 5571cb0ef41Sopenharmony_ci OPENSSL_clear_free(ctx->l, ctx->max_l_index * 16); 5581cb0ef41Sopenharmony_ci OPENSSL_cleanse(ctx, sizeof(*ctx)); 5591cb0ef41Sopenharmony_ci } 5601cb0ef41Sopenharmony_ci} 5611cb0ef41Sopenharmony_ci 5621cb0ef41Sopenharmony_ci#endif /* OPENSSL_NO_OCB */ 563