diff options
Diffstat (limited to 'src/util/crypto/nss/nss_obfuscate.c')
-rw-r--r-- | src/util/crypto/nss/nss_obfuscate.c | 214 |
1 files changed, 14 insertions, 200 deletions
diff --git a/src/util/crypto/nss/nss_obfuscate.c b/src/util/crypto/nss/nss_obfuscate.c index 8c6bdc525..a55f22b6d 100644 --- a/src/util/crypto/nss/nss_obfuscate.c +++ b/src/util/crypto/nss/nss_obfuscate.c @@ -31,42 +31,17 @@ */ #include "config.h" - #include <prerror.h> -#include <nss.h> #include <pk11func.h> -#include <base64.h> -#include <talloc.h> #include "util/util.h" #include "util/crypto/sss_crypto.h" #include "util/crypto/nss/nss_util.h" +#include "util/crypto/nss/nss_crypto.h" #define OBF_BUFFER_SENTINEL "\0\1\2\3" #define OBF_BUFFER_SENTINEL_SIZE 4 -#define MAKE_SECITEM(sdata, slen, sitem) do { \ - (sitem)->type = (siBuffer); \ - (sitem)->data = (sdata); \ - (sitem)->len = (slen); \ -} while(0) - -struct sss_nss_crypto_ctx { - PK11SlotInfo *slot; - PK11Context *ectx; - PK11SymKey *keyobj; - SECItem *sparam; - - SECItem *iv; - SECItem *key; -}; - -struct crypto_mech_data { - CK_MECHANISM_TYPE cipher; - uint16_t keylen; - uint16_t bsize; -}; - static struct crypto_mech_data cmdata[] = { /* AES with automatic padding, 256b key, 128b block */ { CKM_AES_CBC_PAD, 32, 16 }, @@ -83,147 +58,6 @@ static struct crypto_mech_data *get_crypto_mech_data(enum obfmethod meth) return &cmdata[meth]; } -static int generate_random_key(TALLOC_CTX *mem_ctx, - PK11SlotInfo *slot, - struct crypto_mech_data *mech_props, - SECItem **_key) -{ - SECStatus sret; - SECItem *randkeydata; - SECItem *key = NULL; - PK11SymKey *randkey; - int ret; - - randkey = PK11_KeyGen(slot, mech_props->cipher, - NULL, mech_props->keylen, NULL); - if (randkey == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failure to generate key (err %d)\n", - PR_GetError()); - ret = EIO; - goto done; - } - - sret = PK11_ExtractKeyValue(randkey); - if (sret != SECSuccess) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failure to extract key value (err %d)\n", - PR_GetError()); - ret = EIO; - goto done; - } - - randkeydata = PK11_GetKeyData(randkey); - if (randkeydata == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failure to get key data (err %d)\n", - PR_GetError()); - ret = EIO; - goto done; - } - - /* randkeydata is valid until randkey is. Copy with talloc to - * get a nice memory hierarchy symmetrical in encrypt - * and decrypt case */ - key = talloc_zero(mem_ctx, SECItem); - if (!key) { - ret = ENOMEM; - goto done; - } - - key->data = talloc_memdup(key, randkeydata->data, randkeydata->len); - if (!key->data) { - ret = ENOMEM; - goto done; - } - key->len = randkeydata->len; - - *_key = key; - ret = EOK; -done: - if (ret != EOK) talloc_zfree(key); - PK11_FreeSymKey(randkey); - return ret; -} - -static int sss_nss_crypto_ctx_destructor(struct sss_nss_crypto_ctx *cctx) -{ - if (cctx->ectx) PK11_DestroyContext(cctx->ectx, PR_TRUE); - if (cctx->sparam) SECITEM_FreeItem(cctx->sparam, PR_TRUE); - if (cctx->slot) PK11_FreeSlot(cctx->slot); - if (cctx->keyobj) PK11_FreeSymKey(cctx->keyobj); - - return EOK; -} - -static int nss_ctx_init(TALLOC_CTX *mem_ctx, - struct crypto_mech_data *mech_props, - struct sss_nss_crypto_ctx **_cctx) -{ - struct sss_nss_crypto_ctx *cctx; - int ret; - - cctx = talloc_zero(mem_ctx, struct sss_nss_crypto_ctx); - if (!cctx) { - return ENOMEM; - } - talloc_set_destructor(cctx, sss_nss_crypto_ctx_destructor); - - cctx->slot = PK11_GetBestSlot(mech_props->cipher, NULL); - if (cctx->slot == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to find security device (err %d)\n", - PR_GetError()); - ret = EIO; - goto done; - } - - ret = EOK; - *_cctx = cctx; -done: - if (ret) talloc_zfree(cctx); - return ret; -} - -static int nss_encrypt_decrypt_init(struct crypto_mech_data *mech_props, - bool do_encrypt, - struct sss_nss_crypto_ctx *cctx) -{ - CK_ATTRIBUTE_TYPE op; - int ret; - - op = do_encrypt ? CKA_ENCRYPT : CKA_DECRYPT; - - /* turn the raw key into a key object */ - cctx->keyobj = PK11_ImportSymKey(cctx->slot, mech_props->cipher, - PK11_OriginUnwrap, op, cctx->key, NULL); - if (cctx->keyobj == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failure to import key into NSS (err %d)\n", - PR_GetError()); - ret = EIO; - goto done; - } - - /* turn the raw IV into a initialization vector object */ - cctx->sparam = PK11_ParamFromIV(mech_props->cipher, cctx->iv); - if (cctx->sparam == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failure to set up PKCS11 param (err %d)\n", - PR_GetError()); - ret = EIO; - goto done; - } - - /* Create cipher context */ - cctx->ectx = PK11_CreateContextBySymKey(mech_props->cipher, op, - cctx->keyobj, cctx->sparam); - if (cctx->ectx == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create cipher context (err %d)\n", - PORT_GetError()); - ret = EIO; - goto done; - } - - ret = EOK; -done: - return ret; -} - int sss_password_encrypt(TALLOC_CTX *mem_ctx, const char *password, int plen, enum obfmethod meth, char **obfpwd) { @@ -263,27 +97,14 @@ int sss_password_encrypt(TALLOC_CTX *mem_ctx, const char *password, int plen, goto done; } - ret = nss_ctx_init(tmp_ctx, mech_props, &cctx); + /* Initiualize ctx and generate random encryption and IV key */ + ret = nss_ctx_init(tmp_ctx, mech_props, NULL, 1, NULL, 1, &cctx); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context\n"); goto done; } - /* generate random encryption and IV key */ - ret = generate_random_key(cctx, cctx->slot, mech_props, &cctx->key); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not generate encryption key\n"); - goto done; - } - - ret = generate_random_key(cctx, cctx->slot, mech_props, &cctx->iv); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Could not generate initialization vector\n"); - goto done; - } - - ret = nss_encrypt_decrypt_init(mech_props, true, cctx); + ret = nss_crypto_init(mech_props, op_encrypt, cctx); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context properties\n"); @@ -431,7 +252,8 @@ int sss_password_decrypt(TALLOC_CTX *mem_ctx, char *b64encoded, memcpy(sentinel_check, obfbuf + p + mech_props->keylen + mech_props->bsize + ctsize, OBF_BUFFER_SENTINEL_SIZE); - if (memcmp(sentinel_check, OBF_BUFFER_SENTINEL, OBF_BUFFER_SENTINEL_SIZE) != 0) { + if (memcmp(sentinel_check, + OBF_BUFFER_SENTINEL, OBF_BUFFER_SENTINEL_SIZE) != 0) { DEBUG(SSSDBG_FATAL_FAILURE, "Obfuscation buffer seems corrupt, aborting\n"); ret = EFAULT; @@ -460,23 +282,15 @@ int sss_password_decrypt(TALLOC_CTX *mem_ctx, char *b64encoded, } safealign_memcpy(cryptotext, obfbuf+p, ctsize, &p); - ret = nss_ctx_init(tmp_ctx, mech_props, &cctx); + ret = nss_ctx_init(tmp_ctx, mech_props, + keybuf, mech_props->keylen, + ivbuf, mech_props->bsize, &cctx); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context\n"); goto done; } - cctx->iv = talloc_zero(cctx, SECItem); - cctx->key = talloc_zero(cctx, SECItem); - if (!cctx->iv || !cctx->key) { - ret = ENOMEM; - goto done; - } - - MAKE_SECITEM(ivbuf, mech_props->bsize, cctx->iv); - MAKE_SECITEM(keybuf, mech_props->keylen, cctx->key); - - ret = nss_encrypt_decrypt_init(mech_props, false, cctx); + ret = nss_crypto_init(mech_props, op_decrypt, cctx); if (ret) { goto done; } @@ -487,8 +301,8 @@ int sss_password_decrypt(TALLOC_CTX *mem_ctx, char *b64encoded, goto done; } - sret = PK11_CipherOp(cctx->ectx, (unsigned char *) pwdbuf, &plainlen, ctsize, - cryptotext, ctsize); + sret = PK11_CipherOp(cctx->ectx, (unsigned char *) pwdbuf, &plainlen, + ctsize, cryptotext, ctsize); if (sret != SECSuccess) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot execute the encryption operation (err %d)\n", @@ -497,8 +311,8 @@ int sss_password_decrypt(TALLOC_CTX *mem_ctx, char *b64encoded, goto done; } - sret = PK11_DigestFinal(cctx->ectx, (unsigned char *) pwdbuf+plainlen, &digestlen, - ctsize - plainlen); + sret = PK11_DigestFinal(cctx->ectx, (unsigned char *) pwdbuf+plainlen, + &digestlen, ctsize - plainlen); if (sret != SECSuccess) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot execute the encryption operation (err %d)\n", |