Beispiel #1
0
static int local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
                         const char *secret, const char *enctype,
                         char **plain_secret)
{
    char *output;

    if (enctype && strcmp(enctype, "masterkey") == 0) {
        DEBUG(SSSDBG_TRACE_INTERNAL, "Decrypting with masterkey\n");

        struct sec_data _secret;
        size_t outlen;
        int ret;

        _secret.data = (char *)sss_base64_decode(mem_ctx, secret,
                                                 &_secret.length);
        if (!_secret.data) {
            DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed\n");
            return EINVAL;
        }

        ret = sss_decrypt(mem_ctx, AES256CBC_HMAC_SHA256,
                          (uint8_t *)lctx->master_key.data,
                          lctx->master_key.length,
                          (uint8_t *)_secret.data, _secret.length,
                          (uint8_t **)&output, &outlen);
        if (ret) {
            DEBUG(SSSDBG_OP_FAILURE,
                  "sss_decrypt failed [%d]: %s\n", ret, sss_strerror(ret));
            return ret;
        }

        if (((strnlen(output, outlen) + 1) != outlen) ||
            output[outlen - 1] != '\0') {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  "Output length mismatch or output not NULL-terminated\n");
            return EIO;
        }
    } else {
        output = talloc_strdup(mem_ctx, secret);
        if (!output) return ENOMEM;
    }

    *plain_secret = output;
    return EOK;
}
Beispiel #2
0
END_TEST

START_TEST(test_base64_decode)
{
    unsigned char *obfbuf = NULL;
    size_t obflen;
    const char b64encoded[] = "dGVzdA==";
    const unsigned char expected[] = "test";

    test_ctx = talloc_new(NULL);
    fail_if(test_ctx == NULL);
    /* Base64 decode the buffer */
    obfbuf = sss_base64_decode(test_ctx, b64encoded, &obflen);
    fail_if(!obfbuf);
    fail_if(obflen != strlen((const char*)expected));
    fail_if(memcmp(obfbuf, expected, obflen) != 0);

    talloc_free(test_ctx);
}
Beispiel #3
0
int sss_password_decrypt(TALLOC_CTX *mem_ctx, char *b64encoded,
                         char **password)
{
    SECStatus sret;
    int ret;
    TALLOC_CTX *tmp_ctx = NULL;
    struct crypto_mech_data *mech_props;
    struct sss_nss_crypto_ctx *cctx;

    int plainlen;
    unsigned int digestlen;
    unsigned char *obfbuf = NULL;
    size_t obflen;
    char *pwdbuf;

    /* for unmarshaling data */
    uint16_t meth;
    uint16_t ctsize;
    size_t p = 0;
    unsigned char *cryptotext;
    unsigned char *keybuf;
    unsigned char *ivbuf;
    unsigned char sentinel_check[OBF_BUFFER_SENTINEL_SIZE];

    tmp_ctx = talloc_new(mem_ctx);
    if (!tmp_ctx) {
        return ENOMEM;
    }

    /* initialize NSS if needed */
    ret = nspr_nss_init();
    if (ret != EOK) {
        ret = EIO;
        goto done;
    }

    /* Base64 decode the incoming buffer */
    obfbuf = sss_base64_decode(tmp_ctx, b64encoded, &obflen);
    if (!obfbuf) {
        ret = ENOMEM;
        goto done;
    }

    /* unpack obfuscation buffer */
    SAFEALIGN_COPY_UINT16_CHECK(&meth, obfbuf+p, obflen, &p);
    DEBUG(SSSDBG_TRACE_INTERNAL, "Read method: %d\n", meth);
    SAFEALIGN_COPY_UINT16_CHECK(&ctsize, obfbuf+p, obflen, &p);
    DEBUG(SSSDBG_TRACE_INTERNAL, "Read bufsize: %d\n", ctsize);

    mech_props = get_crypto_mech_data(meth);
    if (mech_props == NULL) {
        ret = EINVAL;
        goto done;
    }

    /* check that we got sane mechanism properties and cryptotext size */
    memcpy(sentinel_check,
           obfbuf + p + mech_props->keylen + mech_props->bsize + ctsize,
           OBF_BUFFER_SENTINEL_SIZE);
    if (memcmp(sentinel_check, OBF_BUFFER_SENTINEL, OBF_BUFFER_SENTINEL_SIZE) != 0) {
        DEBUG(SSSDBG_FATAL_FAILURE,
              "Obfuscation buffer seems corrupt, aborting\n");
        ret = EFAULT;
        goto done;
    }

    /* copy out key, ivbuf and cryptotext */
    keybuf = talloc_array(tmp_ctx, unsigned char, mech_props->keylen);
    if (keybuf == NULL) {
        ret = ENOMEM;
        goto done;
    }
    safealign_memcpy(keybuf, obfbuf+p, mech_props->keylen, &p);

    ivbuf = talloc_array(tmp_ctx, unsigned char, mech_props->bsize);
    if (ivbuf == NULL) {
        ret = ENOMEM;
        goto done;
    }
    safealign_memcpy(ivbuf, obfbuf+p, mech_props->bsize, &p);

    cryptotext = talloc_array(tmp_ctx, unsigned char, ctsize);
    if (cryptotext == NULL) {
        ret = ENOMEM;
        goto done;
    }
    safealign_memcpy(cryptotext, obfbuf+p, ctsize, &p);

    ret = nss_ctx_init(tmp_ctx, mech_props, &cctx);
    if (ret) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context\n");
        goto done;
    }

    cctx->iv = talloc_zero(cctx, SECItem);
    cctx->key = talloc_zero(cctx, SECItem);
    if (!cctx->iv || !cctx->key) {
        ret = ENOMEM;
        goto done;
    }

    MAKE_SECITEM(ivbuf, mech_props->bsize, cctx->iv);
    MAKE_SECITEM(keybuf, mech_props->keylen, cctx->key);

    ret = nss_encrypt_decrypt_init(mech_props, false, cctx);
    if (ret) {
        goto done;
    }

    pwdbuf = talloc_array(tmp_ctx, char, ctsize);
    if (!pwdbuf) {
        ret = ENOMEM;
        goto done;
    }

    sret = PK11_CipherOp(cctx->ectx, (unsigned char *) pwdbuf, &plainlen, ctsize,
                         cryptotext, ctsize);
    if (sret != SECSuccess) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "Cannot execute the encryption operation (err %d)\n",
                   PR_GetError());
        ret = EIO;
        goto done;
    }

    sret = PK11_DigestFinal(cctx->ectx, (unsigned char *) pwdbuf+plainlen, &digestlen,
                            ctsize - plainlen);
    if (sret != SECSuccess) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "Cannot execute the encryption operation (err %d)\n",
                   PR_GetError());
        ret = EIO;
        goto done;
    }

    *password = talloc_move(mem_ctx, &pwdbuf);
    ret = EOK;
done:
    talloc_free(tmp_ctx);
    nspr_nss_cleanup();
    return ret;
}