123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570 |
- /*
- * xfm.c
- *
- * Crypto transform implementation
- *
- * David A. McGrew
- * Cisco Systems, Inc.
- */
- #include "cryptoalg.h"
- #include "aes_cbc.h"
- #include "hmac.h"
- #include "crypto_kernel.h" /* for crypto_get_random() */
- #define KEY_LEN 16
- #define ENC_KEY_LEN 16
- #define MAC_KEY_LEN 16
- #define IV_LEN 16
- #define TAG_LEN 12
- #define MAX_EXPAND 27
- err_status_t
- aes_128_cbc_hmac_sha1_96_func(void *key,
- void *clear,
- unsigned clear_len,
- void *iv,
- void *opaque,
- unsigned *opaque_len,
- void *auth_tag) {
- aes_cbc_ctx_t aes_ctx;
- hmac_ctx_t hmac_ctx;
- unsigned char enc_key[ENC_KEY_LEN];
- unsigned char mac_key[MAC_KEY_LEN];
- err_status_t status;
- /* check if we're doing authentication only */
- if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
-
- /* perform authentication only */
- } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
-
- /*
- * bad parameter - we expect either all three pointers to be NULL,
- * or none of those pointers to be NULL
- */
- return err_status_fail;
- } else {
- /* derive encryption and authentication keys from the input key */
- status = hmac_init(&hmac_ctx, key, KEY_LEN);
- if (status) return status;
- status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
- if (status) return status;
- status = hmac_init(&hmac_ctx, key, KEY_LEN);
- if (status) return status;
- status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
- if (status) return status;
- /* perform encryption and authentication */
- /* set aes key */
- status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_encrypt);
- if (status) return status;
- /* set iv */
- status = crypto_get_random(iv, IV_LEN);
- if (status) return status;
- status = aes_cbc_set_iv(&aes_ctx, iv);
-
- /* encrypt the opaque data */
- status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len);
- if (status) return status;
- /* authenticate clear and opaque data */
- status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
- if (status) return status;
- status = hmac_start(&hmac_ctx);
- if (status) return status;
- status = hmac_update(&hmac_ctx, clear, clear_len);
- if (status) return status;
- status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag);
- if (status) return status;
- }
- return err_status_ok;
- }
- err_status_t
- aes_128_cbc_hmac_sha1_96_inv(void *key,
- void *clear,
- unsigned clear_len,
- void *iv,
- void *opaque,
- unsigned *opaque_len,
- void *auth_tag) {
- aes_cbc_ctx_t aes_ctx;
- hmac_ctx_t hmac_ctx;
- unsigned char enc_key[ENC_KEY_LEN];
- unsigned char mac_key[MAC_KEY_LEN];
- unsigned char tmp_tag[TAG_LEN];
- unsigned char *tag = auth_tag;
- err_status_t status;
- int i;
-
- /* check if we're doing authentication only */
- if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
-
- /* perform authentication only */
- } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
-
- /*
- * bad parameter - we expect either all three pointers to be NULL,
- * or none of those pointers to be NULL
- */
- return err_status_fail;
- } else {
- /* derive encryption and authentication keys from the input key */
- status = hmac_init(&hmac_ctx, key, KEY_LEN);
- if (status) return status;
- status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
- if (status) return status;
- status = hmac_init(&hmac_ctx, key, KEY_LEN);
- if (status) return status;
- status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
- if (status) return status;
- /* perform encryption and authentication */
- /* set aes key */
- status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_decrypt);
- if (status) return status;
- /* set iv */
- status = rand_source_get_octet_string(iv, IV_LEN);
- if (status) return status;
- status = aes_cbc_set_iv(&aes_ctx, iv);
-
- /* encrypt the opaque data */
- status = aes_cbc_nist_decrypt(&aes_ctx, opaque, opaque_len);
- if (status) return status;
- /* authenticate clear and opaque data */
- status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
- if (status) return status;
- status = hmac_start(&hmac_ctx);
- if (status) return status;
- status = hmac_update(&hmac_ctx, clear, clear_len);
- if (status) return status;
- status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, tmp_tag);
- if (status) return status;
- /* compare the computed tag with the one provided as input */
- for (i=0; i < TAG_LEN; i++)
- if (tmp_tag[i] != tag[i])
- return err_status_auth_fail;
- }
- return err_status_ok;
- }
- #define ENC 1
- #define DEBUG_PRINT 0
- err_status_t
- aes_128_cbc_hmac_sha1_96_enc(void *key,
- const void *clear,
- unsigned clear_len,
- void *iv,
- void *opaque,
- unsigned *opaque_len) {
- aes_cbc_ctx_t aes_ctx;
- hmac_ctx_t hmac_ctx;
- unsigned char enc_key[ENC_KEY_LEN];
- unsigned char mac_key[MAC_KEY_LEN];
- unsigned char *auth_tag;
- err_status_t status;
- /* check if we're doing authentication only */
- if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
-
- /* perform authentication only */
- } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
-
- /*
- * bad parameter - we expect either all three pointers to be NULL,
- * or none of those pointers to be NULL
- */
- return err_status_fail;
- } else {
- #if DEBUG_PRINT
- printf("ENC using key %s\n", octet_string_hex_string(key, KEY_LEN));
- #endif
- /* derive encryption and authentication keys from the input key */
- status = hmac_init(&hmac_ctx, key, KEY_LEN);
- if (status) return status;
- status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
- if (status) return status;
- status = hmac_init(&hmac_ctx, key, KEY_LEN);
- if (status) return status;
- status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
- if (status) return status;
- /* perform encryption and authentication */
- /* set aes key */
- status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_encrypt);
- if (status) return status;
- /* set iv */
- status = rand_source_get_octet_string(iv, IV_LEN);
- if (status) return status;
- status = aes_cbc_set_iv(&aes_ctx, iv);
- if (status) return status;
- #if DEBUG_PRINT
- printf("plaintext len: %d\n", *opaque_len);
- printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
- printf("plaintext: %s\n", octet_string_hex_string(opaque, *opaque_len));
- #endif
- #if ENC
- /* encrypt the opaque data */
- status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len);
- if (status) return status;
- #endif
- #if DEBUG_PRINT
- printf("ciphertext len: %d\n", *opaque_len);
- printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len));
- #endif
- /*
- * authenticate clear and opaque data, then write the
- * authentication tag to the location immediately following the
- * ciphertext
- */
- status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
- if (status) return status;
- status = hmac_start(&hmac_ctx);
- if (status) return status;
- status = hmac_update(&hmac_ctx, clear, clear_len);
- if (status) return status;
- #if DEBUG_PRINT
- printf("hmac input: %s\n",
- octet_string_hex_string(clear, clear_len));
- #endif
- auth_tag = (unsigned char *)opaque;
- auth_tag += *opaque_len;
- status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag);
- if (status) return status;
- #if DEBUG_PRINT
- printf("hmac input: %s\n",
- octet_string_hex_string(opaque, *opaque_len));
- #endif
- /* bump up the opaque_len to reflect the authentication tag */
- *opaque_len += TAG_LEN;
- #if DEBUG_PRINT
- printf("prot data len: %d\n", *opaque_len);
- printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len));
- #endif
- }
- return err_status_ok;
- }
- err_status_t
- aes_128_cbc_hmac_sha1_96_dec(void *key,
- const void *clear,
- unsigned clear_len,
- void *iv,
- void *opaque,
- unsigned *opaque_len) {
- aes_cbc_ctx_t aes_ctx;
- hmac_ctx_t hmac_ctx;
- unsigned char enc_key[ENC_KEY_LEN];
- unsigned char mac_key[MAC_KEY_LEN];
- unsigned char tmp_tag[TAG_LEN];
- unsigned char *auth_tag;
- unsigned ciphertext_len;
- err_status_t status;
- int i;
-
- /* check if we're doing authentication only */
- if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
-
- /* perform authentication only */
- } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
-
- /*
- * bad parameter - we expect either all three pointers to be NULL,
- * or none of those pointers to be NULL
- */
- return err_status_fail;
- } else {
- #if DEBUG_PRINT
- printf("DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));
- #endif
- /* derive encryption and authentication keys from the input key */
- status = hmac_init(&hmac_ctx, key, KEY_LEN);
- if (status) return status;
- status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
- if (status) return status;
- status = hmac_init(&hmac_ctx, key, KEY_LEN);
- if (status) return status;
- status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
- if (status) return status;
- #if DEBUG_PRINT
- printf("prot data len: %d\n", *opaque_len);
- printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len));
- #endif
- /*
- * set the protected data length to that of the ciphertext, by
- * subtracting out the length of the authentication tag
- */
- ciphertext_len = *opaque_len - TAG_LEN;
- #if DEBUG_PRINT
- printf("ciphertext len: %d\n", ciphertext_len);
- #endif
- /* verify the authentication tag */
- /*
- * compute the authentication tag for the clear and opaque data,
- * and write it to a temporary location
- */
- status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
- if (status) return status;
- status = hmac_start(&hmac_ctx);
- if (status) return status;
- status = hmac_update(&hmac_ctx, clear, clear_len);
- if (status) return status;
- #if DEBUG_PRINT
- printf("hmac input: %s\n",
- octet_string_hex_string(clear, clear_len));
- #endif
- status = hmac_compute(&hmac_ctx, opaque, ciphertext_len, TAG_LEN, tmp_tag);
- if (status) return status;
- #if DEBUG_PRINT
- printf("hmac input: %s\n",
- octet_string_hex_string(opaque, ciphertext_len));
- #endif
- /*
- * compare the computed tag with the one provided as input (which
- * immediately follows the ciphertext)
- */
- auth_tag = (unsigned char *)opaque;
- auth_tag += ciphertext_len;
- #if DEBUG_PRINT
- printf("auth_tag: %s\n", octet_string_hex_string(auth_tag, TAG_LEN));
- printf("tmp_tag: %s\n", octet_string_hex_string(tmp_tag, TAG_LEN));
- #endif
- for (i=0; i < TAG_LEN; i++) {
- if (tmp_tag[i] != auth_tag[i])
- return err_status_auth_fail;
- }
- /* bump down the opaque_len to reflect the authentication tag */
- *opaque_len -= TAG_LEN;
- /* decrypt the confidential data */
- status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_decrypt);
- if (status) return status;
- status = aes_cbc_set_iv(&aes_ctx, iv);
- if (status) return status;
- #if DEBUG_PRINT
- printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len));
- printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
- #endif
- #if ENC
- status = aes_cbc_nist_decrypt(&aes_ctx, opaque, &ciphertext_len);
- if (status) return status;
- #endif
- #if DEBUG_PRINT
- printf("plaintext len: %d\n", ciphertext_len);
- printf("plaintext: %s\n",
- octet_string_hex_string(opaque, ciphertext_len));
- #endif
- /* indicate the length of the plaintext */
- *opaque_len = ciphertext_len;
- }
- return err_status_ok;
- }
- cryptoalg_ctx_t cryptoalg_ctx = {
- aes_128_cbc_hmac_sha1_96_enc,
- aes_128_cbc_hmac_sha1_96_dec,
- KEY_LEN,
- IV_LEN,
- TAG_LEN,
- MAX_EXPAND,
- };
- cryptoalg_t cryptoalg = &cryptoalg_ctx;
- #define NULL_TAG_LEN 12
- err_status_t
- null_enc(void *key,
- const void *clear,
- unsigned clear_len,
- void *iv,
- void *opaque,
- unsigned *opaque_len) {
- int i;
- unsigned char *auth_tag;
- unsigned char *init_vec = iv;
- /* check if we're doing authentication only */
- if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
-
- /* perform authentication only */
- } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
-
- /*
- * bad parameter - we expect either all three pointers to be NULL,
- * or none of those pointers to be NULL
- */
- return err_status_fail;
- } else {
- #if DEBUG_PRINT
- printf("NULL ENC using key %s\n", octet_string_hex_string(key, KEY_LEN));
- printf("NULL_TAG_LEN: %d\n", NULL_TAG_LEN);
- printf("plaintext len: %d\n", *opaque_len);
- #endif
- for (i=0; i < IV_LEN; i++)
- init_vec[i] = i + (i * 16);
- #if DEBUG_PRINT
- printf("iv: %s\n",
- octet_string_hex_string(iv, IV_LEN));
- printf("plaintext: %s\n",
- octet_string_hex_string(opaque, *opaque_len));
- #endif
- auth_tag = opaque;
- auth_tag += *opaque_len;
- for (i=0; i < NULL_TAG_LEN; i++)
- auth_tag[i] = i + (i * 16);
- *opaque_len += NULL_TAG_LEN;
- #if DEBUG_PRINT
- printf("protected data len: %d\n", *opaque_len);
- printf("protected data: %s\n",
- octet_string_hex_string(opaque, *opaque_len));
- #endif
- }
- return err_status_ok;
- }
- err_status_t
- null_dec(void *key,
- const void *clear,
- unsigned clear_len,
- void *iv,
- void *opaque,
- unsigned *opaque_len) {
- unsigned char *auth_tag;
-
- /* check if we're doing authentication only */
- if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
-
- /* perform authentication only */
- } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
-
- /*
- * bad parameter - we expect either all three pointers to be NULL,
- * or none of those pointers to be NULL
- */
- return err_status_fail;
- } else {
- #if DEBUG_PRINT
- printf("NULL DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));
- printf("protected data len: %d\n", *opaque_len);
- printf("protected data: %s\n",
- octet_string_hex_string(opaque, *opaque_len));
- #endif
- auth_tag = opaque;
- auth_tag += (*opaque_len - NULL_TAG_LEN);
- #if DEBUG_PRINT
- printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
- #endif
- *opaque_len -= NULL_TAG_LEN;
- #if DEBUG_PRINT
- printf("plaintext len: %d\n", *opaque_len);
- printf("plaintext: %s\n",
- octet_string_hex_string(opaque, *opaque_len));
- #endif
- }
- return err_status_ok;
- }
- cryptoalg_ctx_t null_cryptoalg_ctx = {
- null_enc,
- null_dec,
- KEY_LEN,
- IV_LEN,
- NULL_TAG_LEN,
- MAX_EXPAND,
- };
- cryptoalg_t null_cryptoalg = &null_cryptoalg_ctx;
- int
- cryptoalg_get_id(cryptoalg_t c) {
- if (c == cryptoalg)
- return 1;
- return 0;
- }
- cryptoalg_t
- cryptoalg_find_by_id(int id) {
- switch(id) {
- case 1:
- return cryptoalg;
- default:
- break;
- }
- return 0;
- }
|