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
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek/*
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek * READ ME:
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek *
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek * Please note that password obfuscation does not improve security in any
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek * way. It is just a mechanism to make the password human-unreadable. If you
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek * need to secure passwords in your application, you should probably take a
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek * look at storing passwords in NSS-backed database.
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek */
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek#include "config.h"
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek#include <prerror.h>
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek#include <pk11func.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"
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce#include "util/crypto/nss/nss_crypto.h"
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek#define OBF_BUFFER_SENTINEL "\0\1\2\3"
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek#define OBF_BUFFER_SENTINEL_SIZE 4
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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported cipher type\n");
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek return NULL;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek }
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek return &cmdata[meth];
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 *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
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce /* Initiualize ctx and generate random encryption and IV key */
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = nss_ctx_init(tmp_ctx, mech_props, NULL, 1, NULL, 1, &cctx);
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek if (ret) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context\n");
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek goto done;
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek }
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = nss_crypto_init(mech_props, op_encrypt, cctx);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek if (ret) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Cannot initialize NSS context properties\n");
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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Cannot execute the encryption operation (err %d)\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov 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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Cannot execute the digest operation (err %d)\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov PR_GetError());
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek ret = EIO;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek goto done;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek }
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek result_len = ctlen + digestlen;
9faab6d48145d3a0d7b9a225ed35bdcaa32eca2cLukas Slebodnik if (result_len < 0 || result_len > UINT16_MAX) {
9faab6d48145d3a0d7b9a225ed35bdcaa32eca2cLukas Slebodnik ret = ERANGE;
9faab6d48145d3a0d7b9a225ed35bdcaa32eca2cLukas Slebodnik goto done;
9faab6d48145d3a0d7b9a225ed35bdcaa32eca2cLukas Slebodnik }
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* Pack the obfuscation buffer */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* The buffer consists of:
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek * uint16_t the type of the cipher
9faab6d48145d3a0d7b9a225ed35bdcaa32eca2cLukas Slebodnik * uint16_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 */
9faab6d48145d3a0d7b9a225ed35bdcaa32eca2cLukas Slebodnik obufsize = sizeof(uint16_t) + sizeof(uint16_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
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_INTERNAL, "Writing method: %d\n", meth);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek SAFEALIGN_SET_UINT16(&obfbuf[p], meth, &p);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_INTERNAL, "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 */
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta *obfpwd = sss_base64_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 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;
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta size_t 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 */
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta obfbuf = sss_base64_decode(tmp_ctx, 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);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_INTERNAL, "Read method: %d\n", meth);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek SAFEALIGN_COPY_UINT16_CHECK(&ctsize, obfbuf+p, obflen, &p);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_INTERNAL, "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);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (memcmp(sentinel_check,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce OBF_BUFFER_SENTINEL, OBF_BUFFER_SENTINEL_SIZE) != 0) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "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
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = nss_ctx_init(tmp_ctx, mech_props,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce keybuf, mech_props->keylen,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ivbuf, mech_props->bsize, &cctx);
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek if (ret) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context\n");
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek goto done;
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek }
fd72f761edb0b11265ce3293b56a4a4fa0d1a317Jakub Hrozek
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = nss_crypto_init(mech_props, op_decrypt, 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
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce sret = PK11_CipherOp(cctx->ectx, (unsigned char *) pwdbuf, &plainlen,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ctsize, cryptotext, ctsize);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek if (sret != SECSuccess) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Cannot execute the encryption operation (err %d)\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov PR_GetError());
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek ret = EIO;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek goto done;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek }
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce sret = PK11_DigestFinal(cctx->ectx, (unsigned char *) pwdbuf+plainlen,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce &digestlen, ctsize - plainlen);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek if (sret != SECSuccess) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Cannot execute the encryption operation (err %d)\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov 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 talloc_free(tmp_ctx);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek return ret;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek}