diff options
author | Greg Hudson <ghudson@mit.edu> | 2010-11-19 22:01:32 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2010-11-19 22:01:32 +0000 |
commit | b085c9946d17fde5801e5fa3dd7dfd8eb0700df9 (patch) | |
tree | 4c4d2f665bfd201d4a13252fd97c40f9becab81f /src/lib/crypto/nss/enc_provider/enc_gen.c | |
parent | 2f62797b59b7f10515851f4825d0c112d915cf7f (diff) | |
download | krb5-camellia-cts-cmac.zip krb5-camellia-cts-cmac.tar.gz krb5-camellia-cts-cmac.tar.bz2 |
Add Camellia support to the NSS back end. (It was mostly alreadycamellia-cts-cmac
there, but we needed a cbc-mac function.)
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/camellia-cts-cmac@24523 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/crypto/nss/enc_provider/enc_gen.c')
-rw-r--r-- | src/lib/crypto/nss/enc_provider/enc_gen.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/lib/crypto/nss/enc_provider/enc_gen.c b/src/lib/crypto/nss/enc_provider/enc_gen.c index 6bdf1d0..2927af3 100644 --- a/src/lib/crypto/nss/enc_provider/enc_gen.c +++ b/src/lib/crypto/nss/enc_provider/enc_gen.c @@ -539,6 +539,76 @@ done: return ret; } +krb5_error_code +k5_nss_gen_cbcmac_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech, + const krb5_data *ivec, const krb5_crypto_iov *data, + size_t num_data, krb5_data *output) +{ + krb5_error_code ret = 0; + PK11Context *ctx = NULL; + SECStatus rv; + SECItem *param = NULL; + struct iov_block_state input_pos, output_pos; + unsigned char storage[MAX_BLOCK_SIZE]; + unsigned char iv0[MAX_BLOCK_SIZE]; + unsigned char *ptr = NULL, *lastptr = NULL; + SECItem iv; + size_t blocksize; + int length = 0; + int currentblock; + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + blocksize = PK11_GetBlockSize(mech, NULL); + assert(blocksize <= sizeof(storage)); + if (output->length < blocksize) + return KRB5_BAD_MSIZE; + + if (ivec && ivec->data) { + iv.data = (unsigned char *)ivec->data; + iv.len = ivec->length; + } else { + memset(iv0, 0, sizeof(iv0)); + iv.data = iv0; + iv.len = blocksize; + } + param = PK11_ParamFromIV(mech, &iv); + + ctx = k5_nss_create_context(krb_key, mech, CKA_ENCRYPT, param); + if (ctx == NULL) { + ret = k5_nss_map_last_error(); + goto done; + } + + lastptr = iv.data; + for (currentblock = 0;;currentblock++) { + if (!krb5int_c_iov_get_block_nocopy(storage, blocksize, data, num_data, + &input_pos, &ptr)) + break; + + lastptr = NULL; + + rv = PK11_CipherOp(ctx, ptr, &length, blocksize, ptr, blocksize); + if (rv != SECSuccess) { + ret = k5_nss_map_last_error(); + goto done; + } + + lastptr = ptr; + } + memcpy(output->data, lastptr, blocksize); + +done: + if (ctx) { + PK11_Finalize(ctx); + PK11_DestroyContext(ctx, PR_TRUE); + } + if (param) + SECITEM_FreeItem(param, PR_TRUE); + return ret; +} + void k5_nss_gen_cleanup(krb5_key krb_key) { |