Test::Result run_one_test(const std::string&, const VarMap& vars) override { const size_t keylen = vars.get_req_sz("Keylen"); const size_t taglen = vars.get_req_sz("Taglen"); const std::vector<uint8_t> expected = vars.get_req_bin("Output"); // Test from RFC 7253 Appendix A const std::string algo = "AES-" + std::to_string(keylen); Test::Result result("OCB long"); std::unique_ptr<Botan::BlockCipher> aes(Botan::BlockCipher::create(algo)); if(!aes) { result.note_missing(algo); return result; } Botan::OCB_Encryption enc(aes->clone(), taglen / 8); Botan::OCB_Decryption dec(aes->clone(), taglen / 8); std::vector<uint8_t> key(keylen / 8); key[keylen / 8 - 1] = static_cast<uint8_t>(taglen); enc.set_key(key); dec.set_key(key); const std::vector<uint8_t> empty; std::vector<uint8_t> N(12); std::vector<uint8_t> C; for(size_t i = 0; i != 128; ++i) { const std::vector<uint8_t> S(i); Botan::store_be(static_cast<uint32_t>(3 * i + 1), &N[8]); ocb_encrypt(result, C, enc, dec, N, S, S); Botan::store_be(static_cast<uint32_t>(3 * i + 2), &N[8]); ocb_encrypt(result, C, enc, dec, N, S, empty); Botan::store_be(static_cast<uint32_t>(3 * i + 3), &N[8]); ocb_encrypt(result, C, enc, dec, N, empty, S); } Botan::store_be(static_cast<uint32_t>(385), &N[8]); std::vector<uint8_t> final_result; ocb_encrypt(result, final_result, enc, dec, N, empty, C); result.test_eq("correct value", final_result, expected); return result; }
void CryptState::encrypt(const unsigned char *source, unsigned char *dst, unsigned int plain_length) { unsigned char tag[AES_BLOCK_SIZE]; // First, increase our IV. for (int i=0;i<AES_BLOCK_SIZE;i++) if (++encrypt_iv[i]) break; ocb_encrypt(source, dst+4, plain_length, encrypt_iv, tag); dst[0] = encrypt_iv[0]; dst[1] = tag[0]; dst[2] = tag[1]; dst[3] = tag[2]; }
int ocb_encrypt_authenticate_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen) { int err; ocb_state *ocb; LTC_ARGCHK(key != NULL); LTC_ARGCHK(nonce != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); /* allocate ram */ ocb = XMALLOC(sizeof(ocb_state)); if (ocb == NULL) { return CRYPT_MEM; } if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { goto LBL_ERR; } while (ptlen > (unsigned long)ocb->block_len) { if ((err = ocb_encrypt(ocb, pt, ct)) != CRYPT_OK) { goto LBL_ERR; } ptlen -= ocb->block_len; pt += ocb->block_len; ct += ocb->block_len; } err = ocb_done_encrypt(ocb, pt, ptlen, ct, tag, taglen); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(ocb, sizeof(ocb_state)); #endif XFREE(ocb); return err; }
Test::Result run_one_test(const std::string& algo, const VarMap& vars) override { Test::Result result("OCB wide block long test"); const std::vector<uint8_t> expected = vars.get_req_bin("Output"); std::unique_ptr<Botan::BlockCipher> cipher; size_t bs = 0; if(algo == "SHACAL2") { #if defined(BOTAN_HAS_SHACAL2) cipher = Botan::BlockCipher::create_or_throw("SHACAL2"); bs = 32; #else return {result}; #endif } else { if(algo == "Toy128") bs = 16; else if(algo == "Toy192") bs = 24; else if(algo == "Toy256") bs = 32; else if(algo == "Toy512") bs = 64; else throw Test_Error("Unknown cipher for OCB wide block long test"); cipher.reset(new OCB_Wide_Test_Block_Cipher(bs)); } Botan::OCB_Encryption enc(cipher.release(), std::min<size_t>(bs, 32)); /* Y, string of length min(B, 256) bits Y is defined as follows. K = (0xA0 || 0xA1 || 0xA2 || ...)[1..B] C = <empty string> for i = 0 to 127 do S = (0x50 || 0x51 || 0x52 || ...)[1..8i] N = num2str(3i+1,16) C = C || OCB-ENCRYPT(K,N,S,S) N = num2str(3i+2,16) C = C || OCB-ENCRYPT(K,N,<empty string>,S) N = num2str(3i+3,16) C = C || OCB-ENCRYPT(K,N,S,<empty string>) end for N = num2str(385,16) Y = OCB-ENCRYPT(K,N,C,<empty string>) */ std::vector<uint8_t> key(bs); for(size_t i = 0; i != bs; ++i) key[i] = 0xA0 + i; enc.set_key(key); const std::vector<uint8_t> empty; std::vector<uint8_t> N(2); std::vector<uint8_t> C; for(size_t i = 0; i != 128; ++i) { std::vector<uint8_t> S(i); for(size_t j = 0; j != S.size(); ++j) S[j] = 0x50 + j; Botan::store_be(static_cast<uint16_t>(3 * i + 1), &N[0]); ocb_encrypt(result, C, enc, N, S, S); Botan::store_be(static_cast<uint16_t>(3 * i + 2), &N[0]); ocb_encrypt(result, C, enc, N, S, empty); Botan::store_be(static_cast<uint16_t>(3 * i + 3), &N[0]); ocb_encrypt(result, C, enc, N, empty, S); } Botan::store_be(static_cast<uint16_t>(385), &N[0]); std::vector<uint8_t> final_result; ocb_encrypt(result, final_result, enc, N, empty, C); result.test_eq("correct value", final_result, expected); return result; }