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