69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek Password obfuscation logic
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek Author: Jakub Hrozek <jhrozek@redhat.com>
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek Copyright (C) Red Hat, Inc 2010
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 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 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/>.
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.
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* AES with automatic padding, 256b key, 128b block */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* sentinel */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozekstatic struct crypto_mech_data *get_crypto_mech_data(enum obfmethod meth)
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported cipher type\n");
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozekint sss_password_encrypt(TALLOC_CTX *mem_ctx, const char *password, int plen,
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* initialize NSS if needed */
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);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context\n");
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = nss_crypto_init(mech_props, op_encrypt, cctx);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Cannot initialize NSS context properties\n");
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek plaintext = (unsigned char *) talloc_strndup(tmp_ctx, password, plen);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* cryptotext buffer must be at least len(plaintext)+blocksize */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek cryptotext = talloc_array(tmp_ctx, unsigned char, ct_maxsize);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* sample data we'll encrypt and decrypt */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek sret = PK11_CipherOp(cctx->ectx, cryptotext, &ctlen, ct_maxsize,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Cannot execute the encryption operation (err %d)\n",
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek sret = PK11_DigestFinal(cctx->ectx, cryptotext+ctlen, &digestlen,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Cannot execute the digest operation (err %d)\n",
9faab6d48145d3a0d7b9a225ed35bdcaa32eca2cLukas Slebodnik if (result_len < 0 || result_len > UINT16_MAX) {
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
9faab6d48145d3a0d7b9a225ed35bdcaa32eca2cLukas Slebodnik obufsize = sizeof(uint16_t) + sizeof(uint16_t) +
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek obfbuf = talloc_array(tmp_ctx, unsigned char, obufsize);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_INTERNAL, "Writing method: %d\n", meth);
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 /* Base64 encode the resulting buffer */
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta *obfpwd = sss_base64_encode(mem_ctx, obfbuf, obufsize);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozekint sss_password_decrypt(TALLOC_CTX *mem_ctx, char *b64encoded,
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* for unmarshaling data */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek unsigned char sentinel_check[OBF_BUFFER_SENTINEL_SIZE];
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* initialize NSS if needed */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* Base64 decode the incoming buffer */
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta obfbuf = sss_base64_decode(tmp_ctx, b64encoded, &obflen);
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 /* check that we got sane mechanism properties and cryptotext size */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek obfbuf + p + mech_props->keylen + mech_props->bsize + ctsize,
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce OBF_BUFFER_SENTINEL, OBF_BUFFER_SENTINEL_SIZE) != 0) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Obfuscation buffer seems corrupt, aborting\n");
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* copy out key, ivbuf and cryptotext */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek keybuf = talloc_array(tmp_ctx, unsigned char, mech_props->keylen);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek safealign_memcpy(keybuf, obfbuf+p, mech_props->keylen, &p);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek ivbuf = talloc_array(tmp_ctx, unsigned char, mech_props->bsize);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek safealign_memcpy(ivbuf, obfbuf+p, mech_props->bsize, &p);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek cryptotext = talloc_array(tmp_ctx, unsigned char, ctsize);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek safealign_memcpy(cryptotext, obfbuf+p, ctsize, &p);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context\n");
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce ret = nss_crypto_init(mech_props, op_decrypt, cctx);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce sret = PK11_CipherOp(cctx->ectx, (unsigned char *) pwdbuf, &plainlen,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Cannot execute the encryption operation (err %d)\n",
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce sret = PK11_DigestFinal(cctx->ectx, (unsigned char *) pwdbuf+plainlen,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Cannot execute the encryption operation (err %d)\n",