2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved.
6 * Some parts of this code originally written by Adam Stubblefield,
7 * -- astubble@rice.edu.
12 #include "db_config.h"
15 #include "dbinc/crypto.h"
16 #include "dbinc/hmac.h"
18 #ifdef HAVE_CRYPTO_IPP
22 static void __aes_err __P((ENV *, int));
23 static int __aes_derivekeys __P((ENV *, DB_CIPHER *, u_int8_t *, size_t));
27 * Setup AES functions.
29 * PUBLIC: int __aes_setup __P((ENV *, DB_CIPHER *));
32 __aes_setup(env, db_cipher)
36 AES_CIPHER *aes_cipher;
38 #ifdef HAVE_CRYPTO_IPP
43 db_cipher->adj_size = __aes_adj_size;
44 db_cipher->close = __aes_close;
45 db_cipher->decrypt = __aes_decrypt;
46 db_cipher->encrypt = __aes_encrypt;
47 db_cipher->init = __aes_init;
48 if ((ret = __os_calloc(env, 1, sizeof(AES_CIPHER), &aes_cipher)) != 0)
50 #ifdef HAVE_CRYPTO_IPP
52 * IPP AES encryption context size can only be obtained through this
53 * function call, cannot directly declare IppsRijndael128Spec within
56 if ((ipp_ret = ippsRijndael128GetSize(&ctx_size)) != ippStsNoErr) {
57 __aes_err(env, (int)ipp_ret);
60 if ((ret = __os_malloc(env, ctx_size, &aes_cipher->ipp_ctx)) != 0) {
61 __os_free(env, aes_cipher);
65 db_cipher->data = aes_cipher;
71 * Given a size, return an addition amount needed to meet the
72 * "chunk" needs of the algorithm.
74 * PUBLIC: u_int __aes_adj_size __P((size_t));
80 if (len % DB_AES_CHUNK == 0)
82 return (DB_AES_CHUNK - (u_int)(len % DB_AES_CHUNK));
87 * Destroy the AES encryption instantiation.
89 * PUBLIC: int __aes_close __P((ENV *, void *));
92 __aes_close(env, data)
96 #ifdef HAVE_CRYPTO_IPP
97 AES_CIPHER *aes_cipher = (AES_CIPHER *)data;
98 __os_free(env, aes_cipher->ipp_ctx);
100 __os_free(env, data);
106 * Decrypt data with AES.
108 * PUBLIC: int __aes_decrypt __P((ENV *, void *, void *,
109 * PUBLIC: u_int8_t *, size_t));
112 __aes_decrypt(env, aes_data, iv, cipher, cipher_len)
120 #ifdef HAVE_CRYPTO_IPP
127 aes = (AES_CIPHER *)aes_data;
128 if (iv == NULL || cipher == NULL)
130 if ((cipher_len % DB_AES_CHUNK) != 0)
133 #ifdef HAVE_CRYPTO_IPP
134 if ((ipp_ret = ippsRijndael128DecryptCBC((const Ipp8u *)cipher,
135 (Ipp8u *)cipher, cipher_len, (IppsRijndael128Spec *)aes->ipp_ctx,
136 (const Ipp8u *)iv, 0)) != ippStsNoErr) {
137 __aes_err(env, (int)ipp_ret);
142 * Initialize the cipher
144 if ((ret = __db_cipherInit(&c, MODE_CBC, iv)) < 0) {
149 /* Do the decryption */
150 if ((ret = __db_blockDecrypt(&c, &aes->decrypt_ki, cipher,
151 cipher_len * 8, cipher)) < 0) {
161 * Encrypt data with AES.
163 * PUBLIC: int __aes_encrypt __P((ENV *, void *, void *,
164 * PUBLIC: u_int8_t *, size_t));
167 __aes_encrypt(env, aes_data, iv, data, data_len)
175 #ifdef HAVE_CRYPTO_IPP
180 u_int32_t tmp_iv[DB_IV_BYTES/4];
183 aes = (AES_CIPHER *)aes_data;
184 if (aes == NULL || data == NULL)
186 if ((data_len % DB_AES_CHUNK) != 0)
189 * Generate the IV here. We store it in a tmp IV because
190 * the IV might be stored within the data we are encrypting
191 * and so we will copy it over to the given location after
192 * encryption is done.
193 * We don't do this outside of there because some encryption
194 * algorithms someone might add may not use IV's and we always
197 if ((ret = __db_generate_iv(env, tmp_iv)) != 0)
200 #ifdef HAVE_CRYPTO_IPP
201 if ((ipp_ret = ippsRijndael128EncryptCBC((const Ipp8u *)data,
202 (Ipp8u *)data, data_len, (IppsRijndael128Spec *)aes->ipp_ctx,
203 (const Ipp8u *)tmp_iv, 0)) != ippStsNoErr) {
204 __aes_err(env, (int)ipp_ret);
209 * Initialize the cipher
211 if ((ret = __db_cipherInit(&c, MODE_CBC, (char *)tmp_iv)) < 0) {
216 /* Do the encryption */
217 if ((ret = __db_blockEncrypt(&c, &aes->encrypt_ki, data, data_len * 8,
223 memcpy(iv, tmp_iv, DB_IV_BYTES);
229 * Initialize the AES encryption instantiation.
231 * PUBLIC: int __aes_init __P((ENV *, DB_CIPHER *));
234 __aes_init(env, db_cipher)
236 DB_CIPHER *db_cipher;
242 return (__aes_derivekeys(
243 env, db_cipher, (u_int8_t *)dbenv->passwd, dbenv->passwd_len));
247 __aes_derivekeys(env, db_cipher, passwd, plen)
249 DB_CIPHER *db_cipher;
255 #ifdef HAVE_CRYPTO_IPP
260 u_int32_t temp[DB_MAC_KEY/4];
265 aes = (AES_CIPHER *)db_cipher->data;
267 /* Derive the crypto keys */
269 __db_SHA1Update(&ctx, passwd, plen);
270 __db_SHA1Update(&ctx, (u_int8_t *)DB_ENC_MAGIC, strlen(DB_ENC_MAGIC));
271 __db_SHA1Update(&ctx, passwd, plen);
272 __db_SHA1Final((u_int8_t *)temp, &ctx);
274 #ifdef HAVE_CRYPTO_IPP
275 if ((ipp_ret = ippsRijndael128Init((const Ipp8u *)temp,
276 IppsRijndaelKey128, (IppsRijndael128Spec *)aes->ipp_ctx))
278 __aes_err(env, (int)ipp_ret);
282 if ((ret = __db_makeKey(&aes->encrypt_ki, DIR_ENCRYPT,
283 DB_AES_KEYLEN, (char *)temp)) != TRUE) {
287 if ((ret = __db_makeKey(&aes->decrypt_ki, DIR_DECRYPT,
288 DB_AES_KEYLEN, (char *)temp)) != TRUE) {
298 * Handle AES-specific errors. Codes and messages derived from
299 * rijndael/rijndael-api-fst.h.
309 #ifdef HAVE_CRYPTO_IPP
310 case ippStsNullPtrErr:
311 errstr = DB_STR("0182", "IPP AES NULL pointer error");
313 case ippStsLengthErr:
314 errstr = DB_STR("0183", "IPP AES length error");
316 case ippStsContextMatchErr:
317 errstr = DB_STR("0184",
318 "IPP AES context does not match operation");
320 case ippStsUnderRunErr:
321 errstr = DB_STR("0185", "IPP AES srclen size error");
325 errstr = DB_STR("0186", "AES key direction is invalid");
328 errstr = DB_STR("0187",
329 "AES key material not of correct length");
331 case BAD_KEY_INSTANCE:
332 errstr = DB_STR("0188", "AES key passwd not valid");
334 case BAD_CIPHER_MODE:
335 errstr = DB_STR("0189",
336 "AES cipher in wrong state (not initialized)");
338 case BAD_BLOCK_LENGTH:
339 errstr = DB_STR("0190", "AES bad block length");
341 case BAD_CIPHER_INSTANCE:
342 errstr = DB_STR("0191", "AES cipher instance is invalid");
345 errstr = DB_STR("0192", "AES data contents are invalid");
348 errstr = DB_STR("0193", "AES unknown error");
352 errstr = DB_STR("0194", "AES error unrecognized");
355 __db_errx(env, "%s", errstr);