nss_obfuscate.c revision 911c75f1555742d78568635f1bc0549116eabd4a
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/*
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen SSSD
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen Password obfuscation logic
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen Author: Jakub Hrozek <jhrozek@redhat.com>
6e2856a5beeeb0edf5d852dde63d99fb9af11151Martti Rannanjärvi
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen Copyright (C) Red Hat, Inc 2010
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen This program is free software; you can redistribute it and/or modify
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen it under the terms of the GNU General Public License as published by
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen the Free Software Foundation; either version 3 of the License, or
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen (at your option) any later version.
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen This program is distributed in the hope that it will be useful,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen GNU General Public License for more details.
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen You should have received a copy of the GNU General Public License
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen*/
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen/*
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * READ ME:
ad859755efbf4b0c7787b6868f92ceafffdb368fTimo Sirainen *
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * Please note that password obfuscation does not improve security in any
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * way. It is just a mechanism to make the password human-unreadable. If you
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * need to secure passwords in your application, you should probably take a
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen * look at storing passwords in NSS-backed database.
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "config.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <prerror.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <nss.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <pk11func.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <base64.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <talloc.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen#include "util/util.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "util/crypto/sss_crypto.h"
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen#include "util/crypto/nss/nss_util.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#define OBF_BUFFER_SENTINEL "\0\1\2\3"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#define OBF_BUFFER_SENTINEL_SIZE 4
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#define MAKE_SECITEM(sdata, slen, sitem) do { \
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen (sitem)->type = (siBuffer); \
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen (sitem)->data = (sdata); \
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen (sitem)->len = (slen); \
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen} while(0);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct sss_nss_crypto_ctx {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PK11SlotInfo *slot;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PK11Context *ectx;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PK11SymKey *keyobj;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen SECItem *sparam;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen SECItem *iv;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen SECItem *key;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen};
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct crypto_mech_data {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen CK_MECHANISM_TYPE cipher;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen uint16_t keylen;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen uint16_t bsize;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen};
8d35582f2577c64517b2341c5d6477c7010e0a0cPhil Carmody
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic struct crypto_mech_data cmdata[] = {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* AES with automatic padding, 256b key, 128b block */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen { CKM_AES_CBC_PAD, 32, 16 },
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* sentinel */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen { 0, 0, 0 }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen};
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenstatic struct crypto_mech_data *get_crypto_mech_data(enum obfmethod meth)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen{
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (meth >= NUM_OBFMETHODS) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen DEBUG(1, ("Unsupported cipher type\n"));
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen return NULL;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen return &cmdata[meth];
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen}
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenstatic int generate_random_key(TALLOC_CTX *mem_ctx,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen PK11SlotInfo *slot,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen struct crypto_mech_data *mech_props,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen SECItem **_key)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen{
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen SECStatus sret;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen SECItem *randkeydata;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen SECItem *key = NULL;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen PK11SymKey *randkey;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen int ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen randkey = PK11_KeyGen(slot, mech_props->cipher,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen NULL, mech_props->keylen, NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (randkey == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(1, ("Failure to generate key (err %d)\n",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PR_GetError()));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EIO;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen sret = PK11_ExtractKeyValue(randkey);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (sret != SECSuccess) {
8d35582f2577c64517b2341c5d6477c7010e0a0cPhil Carmody DEBUG(1, ("Failure to extract key value (err %d)\n",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PR_GetError()));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EIO;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen randkeydata = PK11_GetKeyData(randkey);
8d35582f2577c64517b2341c5d6477c7010e0a0cPhil Carmody if (randkey == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(1, ("Failure to get key data (err %d)\n",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PR_GetError()));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EIO;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* randkeydata is valid until randkey is. Copy with talloc to
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * get a nice memory hierarchy symmetrical in encrypt
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * and decrypt case */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen key = talloc_zero(mem_ctx, SECItem);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!key) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = ENOMEM;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen key->data = talloc_memdup(key, randkeydata->data, randkeydata->len);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!key->data) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = ENOMEM;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen key->len = randkeydata->len;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *_key = key;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EOK;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainendone:
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen if (ret != EOK) talloc_zfree(key);
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen PK11_FreeSymKey(randkey);
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainenstatic int sss_nss_crypto_ctx_destructor(struct sss_nss_crypto_ctx *cctx)
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen{
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen if (cctx->ectx) PK11_DestroyContext(cctx->ectx, PR_TRUE);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (cctx->sparam) SECITEM_FreeItem(cctx->sparam, PR_TRUE);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (cctx->slot) PK11_FreeSlot(cctx->slot);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (cctx->keyobj) PK11_FreeSymKey(cctx->keyobj);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return EOK;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int nss_ctx_init(TALLOC_CTX *mem_ctx,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct crypto_mech_data *mech_props,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct sss_nss_crypto_ctx **_cctx)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct sss_nss_crypto_ctx *cctx;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret;
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen cctx = talloc_zero(mem_ctx, struct sss_nss_crypto_ctx);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (!cctx) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ENOMEM;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen talloc_set_destructor(cctx, sss_nss_crypto_ctx_destructor);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen cctx->slot = PK11_GetBestSlot(mech_props->cipher, NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (cctx->slot == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(1, ("Unable to find security device (err %d)\n",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PR_GetError()));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EIO;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EOK;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *_cctx = cctx;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainendone:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ret) talloc_zfree(cctx);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int nss_encrypt_decrypt_init(TALLOC_CTX *mem_ctx,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct crypto_mech_data *mech_props,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen bool encrypt,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct sss_nss_crypto_ctx *cctx)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen CK_ATTRIBUTE_TYPE op;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen op = encrypt ? CKA_ENCRYPT : CKA_DECRYPT;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* turn the raw key into a key object */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen cctx->keyobj = PK11_ImportSymKey(cctx->slot, mech_props->cipher,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PK11_OriginUnwrap, op, cctx->key, NULL);
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen if (cctx->keyobj == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(1, ("Failure to import key into NSS (err %d)\n",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PR_GetError()));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EIO;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* turn the raw IV into a initialization vector object */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen cctx->sparam = PK11_ParamFromIV(mech_props->cipher, cctx->iv);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (cctx->sparam == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(1, ("Failure to set up PKCS11 param (err %d)\n",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PR_GetError()));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EIO;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* Create cipher context */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen cctx->ectx = PK11_CreateContextBySymKey(mech_props->cipher, op,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen cctx->keyobj, cctx->sparam);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (cctx->ectx == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(1, ("Cannot create cipher context (err %d)\n",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PORT_GetError()));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EIO;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EOK;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainendone:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen/* NSS wraps b64 encoded buffers with CRLF automatically after 64 chars. This
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * function strips the CRLF double-chars. The buffer can be decoded with plain
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * NSS calls */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic char *b64_encode(TALLOC_CTX *mem_ctx,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned char *inbuf,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen size_t inbufsize)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen char *b64encoded = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int i, j, b64size;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen char *outbuf;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen b64encoded = BTOA_DataToAscii(inbuf, inbufsize);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!b64encoded) return NULL;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen b64size = strlen(b64encoded) + 1;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen outbuf = talloc_array(mem_ctx, char, b64size);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (outbuf == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PORT_Free(b64encoded);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen for (i=0, j=0; i < b64size; i++) {
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (b64encoded[i] == '\n' || b64encoded[i] == '\r') {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen continue;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen outbuf[j++] = b64encoded[i]; /* will also copy the trailing \0 char */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PORT_Free(b64encoded);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return outbuf;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint sss_password_encrypt(TALLOC_CTX *mem_ctx, const char *password, int plen,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen enum obfmethod meth, char **obfpwd)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen SECStatus sret;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen int ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen TALLOC_CTX *tmp_ctx = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct crypto_mech_data *mech_props;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct sss_nss_crypto_ctx *cctx;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned char *plaintext;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned char *cryptotext;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ct_maxsize;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ctlen;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned int digestlen;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int result_len;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned char *obfbuf;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen size_t obufsize = 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen size_t p = 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen tmp_ctx = talloc_new(mem_ctx);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!tmp_ctx) {
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen return ENOMEM;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* initialize NSS if needed */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = nspr_nss_init();
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ret != EOK) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EIO;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen mech_props = get_crypto_mech_data(meth);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (mech_props == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EINVAL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = nss_ctx_init(tmp_ctx, mech_props, &cctx);
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen if (ret) {
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen DEBUG(1, ("Cannot initialize NSS context\n"));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* generate random encryption and IV key */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = generate_random_key(cctx, cctx->slot, mech_props, &cctx->key);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ret != EOK) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(1, ("Could not generate encryption key\n"));
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen goto done;
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen }
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen ret = generate_random_key(cctx, cctx->slot, mech_props, &cctx->iv);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ret != EOK) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(1, ("Could not generate initialization vector\n"));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen ret = nss_encrypt_decrypt_init(tmp_ctx, mech_props, true, cctx);
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen if (ret) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(1, ("Cannot initialize NSS context properties\n"));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen plaintext = (unsigned char *) talloc_strndup(tmp_ctx, password, plen);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!plaintext) {
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen ret = ENOMEM;
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen goto done;
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen }
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* cryptotext buffer must be at least len(plaintext)+blocksize */
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ct_maxsize = plen + (mech_props->bsize);
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen cryptotext = talloc_array(tmp_ctx, unsigned char, ct_maxsize);
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen if (!cryptotext) {
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen ret = ENOMEM;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen goto done;
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* sample data we'll encrypt and decrypt */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen sret = PK11_CipherOp(cctx->ectx, cryptotext, &ctlen, ct_maxsize,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen plaintext, plen);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (sret != SECSuccess) {
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen DEBUG(1, ("Cannot execute the encryption operation (err %d)\n",
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen PR_GetError()));
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen ret = EIO;
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen goto done;
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen }
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen sret = PK11_DigestFinal(cctx->ectx, cryptotext+ctlen, &digestlen,
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen ct_maxsize-ctlen);
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen if (sret != SECSuccess) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(1, ("Cannot execute the digest operation (err %d)\n",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen PR_GetError()));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = EIO;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen result_len = ctlen + digestlen;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* Pack the obfuscation buffer */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* The buffer consists of:
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * uint16_t the type of the cipher
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * uint32_t length of the cryptotext in bytes (clen)
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen * uint8_t[klen] key
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * uint8_t[blen] IV
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen * uint8_t[clen] cryptotext
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen * 4 bytes of "sentinel" denoting end of the buffer
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen */
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen obufsize = sizeof(uint16_t) + sizeof(uint32_t) +
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mech_props->keylen + mech_props->bsize +
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen result_len + OBF_BUFFER_SENTINEL_SIZE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen obfbuf = talloc_array(tmp_ctx, unsigned char, obufsize);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!obfbuf) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = ENOMEM;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(8, ("Writing method: %d\n", meth));
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen SAFEALIGN_SET_UINT16(&obfbuf[p], meth, &p);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DEBUG(8, ("Writing bufsize: %d\n", result_len));
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen SAFEALIGN_SET_UINT16(&obfbuf[p], result_len, &p);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen safealign_memcpy(&obfbuf[p], cctx->key->data, mech_props->keylen, &p);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen safealign_memcpy(&obfbuf[p], cctx->iv->data, mech_props->bsize, &p);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen safealign_memcpy(&obfbuf[p], cryptotext, result_len, &p);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen safealign_memcpy(&obfbuf[p], OBF_BUFFER_SENTINEL,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen OBF_BUFFER_SENTINEL_SIZE, &p);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* Base64 encode the resulting buffer */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *obfpwd = b64_encode(mem_ctx, obfbuf, obufsize);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (*obfpwd == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = ENOMEM;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen goto done;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ret = EOK;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainendone:
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen talloc_free(tmp_ctx);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen nspr_nss_cleanup();
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen return ret;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen}
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenint sss_password_decrypt(TALLOC_CTX *mem_ctx, char *b64encoded,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen char **password)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen{
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen SECStatus sret;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen int ret;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen TALLOC_CTX *tmp_ctx = NULL;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen struct crypto_mech_data *mech_props;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen struct sss_nss_crypto_ctx *cctx;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen int plainlen;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen unsigned int digestlen;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen unsigned char *obfbuf = NULL;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen unsigned int obflen;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen char *pwdbuf;
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen /* for unmarshaling data */
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen uint16_t meth;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen uint16_t ctsize;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen size_t p = 0;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen unsigned char *cryptotext;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen unsigned char *keybuf;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen unsigned char *ivbuf;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen unsigned char sentinel_check[OBF_BUFFER_SENTINEL_SIZE];
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen tmp_ctx = talloc_new(mem_ctx);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (!tmp_ctx) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen return ENOMEM;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen /* initialize NSS if needed */
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ret = nspr_nss_init();
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (ret != EOK) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ret = EIO;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen goto done;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen /* Base64 decode the incoming buffer */
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen obfbuf = ATOB_AsciiToData(b64encoded, &obflen);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (!obfbuf) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ret = ENOMEM;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen goto done;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen /* unpack obfuscation buffer */
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen SAFEALIGN_COPY_UINT16_CHECK(&meth, obfbuf+p, obflen, &p);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen DEBUG(8, ("Read method: %d\n", meth));
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen SAFEALIGN_COPY_UINT16_CHECK(&ctsize, obfbuf+p, obflen, &p);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen DEBUG(8, ("Read bufsize: %d\n", ctsize));
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen mech_props = get_crypto_mech_data(meth);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (mech_props == NULL) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ret = EINVAL;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen goto done;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen /* check that we got sane mechanism properties and cryptotext size */
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen memcpy(sentinel_check,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen obfbuf + p + mech_props->keylen + mech_props->bsize + ctsize,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen OBF_BUFFER_SENTINEL_SIZE);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (memcmp(sentinel_check, OBF_BUFFER_SENTINEL, OBF_BUFFER_SENTINEL_SIZE) != 0) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen DEBUG(0, ("Obfuscation buffer seems corrupt, aborting\n"));
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ret = EFAULT;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen goto done;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen /* copy out key, ivbuf and cryptotext */
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen keybuf = talloc_array(tmp_ctx, unsigned char, mech_props->keylen);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (keybuf == NULL) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ret = ENOMEM;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen goto done;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen safealign_memcpy(keybuf, obfbuf+p, mech_props->keylen, &p);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ivbuf = talloc_array(tmp_ctx, unsigned char, mech_props->bsize);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (ivbuf == NULL) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ret = ENOMEM;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen goto done;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen safealign_memcpy(ivbuf, obfbuf+p, mech_props->bsize, &p);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen cryptotext = talloc_array(tmp_ctx, unsigned char, ctsize);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (cryptotext == NULL) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ret = ENOMEM;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen goto done;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen safealign_memcpy(cryptotext, obfbuf+p, ctsize, &p);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ret = nss_ctx_init(tmp_ctx, mech_props, &cctx);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (ret) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen DEBUG(1, ("Cannot initialize NSS context\n"));
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen goto done;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen cctx->iv = talloc_zero(cctx, SECItem);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen cctx->key = talloc_zero(cctx, SECItem);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (!cctx->iv || !cctx->key) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ret = ENOMEM;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen goto done;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen MAKE_SECITEM(ivbuf, mech_props->bsize, cctx->iv);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen MAKE_SECITEM(keybuf, mech_props->keylen, cctx->key);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen ret = nss_encrypt_decrypt_init(tmp_ctx, mech_props, false, cctx);
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen if (ret) {
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen goto done;
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen }
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen pwdbuf = talloc_array(tmp_ctx, char, ctsize);
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen if (!pwdbuf) {
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen ret = ENOMEM;
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen goto done;
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen }
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen sret = PK11_CipherOp(cctx->ectx, (unsigned char *) pwdbuf, &plainlen, ctsize,
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen cryptotext, ctsize);
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen if (sret != SECSuccess) {
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen DEBUG(1, ("Cannot execute the encryption operation (err %d)\n",
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen PR_GetError()));
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen ret = EIO;
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen goto done;
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen }
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen sret = PK11_DigestFinal(cctx->ectx, (unsigned char *) pwdbuf+plainlen, &digestlen,
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen ctsize - plainlen);
12c57531519d66e237e865c6ee3f7eadfe148550Timo Sirainen if (sret != SECSuccess) {
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen DEBUG(1, ("Cannot execute the encryption operation (err %d)\n",
PR_GetError()));
ret = EIO;
goto done;
}
*password = talloc_move(mem_ctx, &pwdbuf);
ret = EOK;
done:
PORT_Free(obfbuf);
talloc_free(tmp_ctx);
nspr_nss_cleanup();
return ret;
}