Example #1
0
void
_libssh2_wincng_cipher_dtor(_libssh2_cipher_ctx *ctx)
{
    BCryptDestroyKey(ctx->hKey);

    if (ctx->pbKeyObject) {
        free(ctx->pbKeyObject);
        ctx->pbKeyObject = NULL;
    }

    memset(ctx, 0, sizeof(_libssh2_cipher_ctx));
}
Example #2
0
void
_libssh2_wincng_rsa_free(libssh2_rsa_ctx *rsa)
{
    if (!rsa)
        return;

    BCryptDestroyKey(rsa->hKey);

    if (rsa->pbKeyObject)
        free(rsa->pbKeyObject);

    memset(rsa, 0, sizeof(libssh2_rsa_ctx));
    free(rsa);
}
static int
aes_ctr_release(archive_crypto_ctx *ctx)
{

	if (ctx->hAlg != NULL) {
		BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
		ctx->hAlg = NULL;
		BCryptDestroyKey(ctx->hKey);
		ctx->hKey = NULL;
		HeapFree(GetProcessHeap(), 0, ctx->keyObj);
		ctx->keyObj = NULL;
	}
	memset(ctx, 0, sizeof(*ctx));
	return 0;
}
Example #4
0
int aes_transformkey(m0_kdbx_header_entry_t *hdr, uint8_t *tkey, size_t tkeylen)
{
  BCRYPT_ALG_HANDLE aes            = NULL;
  BCRYPT_KEY_HANDLE key            = NULL;
  NTSTATUS          status         = 0;
  DWORD             len_ciphertext = 0,
                    tmp_len        = 0,
                    key_objectlen  = 0;

  PBYTE             key_object     = NULL;
  uint64_t          rounds         = 0;

  // Open an algorithm handle.
  status = BCryptOpenAlgorithmProvider(
                &aes,
                BCRYPT_AES_ALGORITHM,
                NULL,
                0);

  if(!NT_SUCCESS(status)) {
    printf("[!] Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
    goto cleanup;
  }

  // Calculate the size of the buffer to hold the KeyObject.
  status = BCryptGetProperty(
                aes,
                BCRYPT_OBJECT_LENGTH,
                (PBYTE)&key_objectlen,
                sizeof(DWORD),
                &tmp_len,
                0);

  if(!NT_SUCCESS(status)) {
    printf("[!] Error 0x%x returned by BCryptGetProperty\n", status);
    goto cleanup;
  }

  // Allocate the key object on the heap.
  key_object = (PBYTE)HeapAlloc(GetProcessHeap(), 0, key_objectlen);

  if(NULL == key_object)     {
    printf("[!] memory allocation failed\n");
    goto cleanup;
  }

  status = BCryptSetProperty(
                aes,
                BCRYPT_CHAINING_MODE,
                (PBYTE)BCRYPT_CHAIN_MODE_ECB,
                sizeof(BCRYPT_CHAIN_MODE_ECB),
                0);

  if(!NT_SUCCESS(status)) {
    printf("[!] Error 0x%x returned by BCryptSetProperty\n", status);
    goto cleanup;
  }

  // Generate the key from supplied input key bytes.
  status = BCryptGenerateSymmetricKey(
                aes,
                &key,
                key_object,
                key_objectlen,
                hdr[TRANSFORMSEED].data,
                hdr[TRANSFORMSEED].len,
                0);

  if(!NT_SUCCESS(status)) {
    printf("[!] Error 0x%x returned by BCryptGenerateSymmetricKey\n", status);
    goto cleanup;
  }

  status = BCryptEncrypt(
                key,
                tkey,
                tkeylen,
                NULL,
                NULL,
                0,
                NULL,
                0,
                &len_ciphertext,
                0);

  if(!NT_SUCCESS(status)) {
    printf("[!] Error 0x%x returned by BCryptEncrypt (calculate)\n", status);
    goto cleanup;
  }

  for(rounds = 0; rounds < hdr[TRANSFORMROUNDS].qw; rounds++) {

    status = BCryptEncrypt(
                key,
                tkey,
                tkeylen,
                NULL,
                NULL,
                0,
                tkey,
                tkeylen,
                &tmp_len,
                0);

    if(!NT_SUCCESS(status)) {
      printf("[!] Error 0x%x returned by BCryptEncrypt (encrypt)\n", status);
      goto cleanup;
    }
  }

cleanup:

  if(aes) {
    BCryptCloseAlgorithmProvider(aes,0);
  }

  if (key) {
    BCryptDestroyKey(key);
  }

  if(key_object) {
    HeapFree(GetProcessHeap(), 0, key_object);
  }

  return status;
}
Example #5
0
bool aes_decrypt_check(m0_kdbx_header_entry_t *hdr, uint8_t *masterkey, m0_kdbx_payload_t *payload)
{
  bool res = false;

  BCRYPT_ALG_HANDLE aes            = NULL;
  BCRYPT_KEY_HANDLE ctx            = NULL;
  NTSTATUS          status         = 0;
  DWORD             len_ciphertext = 0,
                    tmp_len        = 0,
                    key_objectlen  = 0;

  PBYTE             key_object     = NULL;

  uint8_t           plaintext[32]  = {0};
  uint8_t           iv[256]        = {0};
  uint8_t           ivlen          = hdr[ENCRYPTIONIV].len & 0xFF;

  // we need to create a local copy of IV, as it is modified during decryption.
  memcpy(&iv, hdr[ENCRYPTIONIV].data, ivlen);

  // Open an algorithm handle.
  status = BCryptOpenAlgorithmProvider(
                  &aes,
                  BCRYPT_AES_ALGORITHM,
                  NULL,
                  0);

  if(!NT_SUCCESS(status)) {
    printf("[!] Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
    goto cleanup;
  }

  // Calculate the size of the buffer to hold the Key Object.
  status = BCryptGetProperty(
                  aes,
                  BCRYPT_OBJECT_LENGTH,
                  (PBYTE)&key_objectlen,
                  sizeof(DWORD),
                  &tmp_len,
                  0);

  if(!NT_SUCCESS(status)) {
    printf("[!] Error 0x%x returned by BCryptGetProperty\n", status);
    goto cleanup;
  }

  // We should use preallocated memory for better performance...
  key_object = (PBYTE)HeapAlloc(GetProcessHeap(), 0, key_objectlen);

  if(NULL == key_object) {
    printf("[!] memory allocation failed\n");
    goto cleanup;
  }

  status = BCryptSetProperty(
                  aes,
                  BCRYPT_CHAINING_MODE,
                  (PBYTE)BCRYPT_CHAIN_MODE_CBC,
                  sizeof(BCRYPT_CHAIN_MODE_CBC),
                  0);

  if(!NT_SUCCESS(status)) {
    printf("[!] Error 0x%x returned by BCryptSetProperty\n", status);
    goto cleanup;
  }

  // Generate the key from supplied input key bytes.
  status = BCryptGenerateSymmetricKey(
                  aes,
                  &ctx,
                  key_object,
                  key_objectlen,
                  masterkey,
                  32,
                  0);

  if(!NT_SUCCESS(status)) {
    printf("[!] Error 0x%x returned by BCryptGenerateSymmetricKey\n", status);
    goto cleanup;
  }

  status = BCryptDecrypt(
                  ctx,
                  payload->encrypted,
                  hdr[STREAMSTARTBYTES].len,
                  NULL,
                  iv,
                  ivlen,
                  plaintext,
                  sizeof(plaintext),
                  &tmp_len,
                  0);

  if(!NT_SUCCESS(status)) {
    printf("[!] Error 0x%x returned by BCryptDecrypt\n", status);
    goto cleanup;
  }

  // success!
  if (0 == memcmp(plaintext, hdr[STREAMSTARTBYTES].data, hdr[STREAMSTARTBYTES].len)) {
    res = true;
    payload->decrypted = malloc(hdr[STREAMSTARTBYTES].len);
    memcpy(payload->decrypted, plaintext, hdr[STREAMSTARTBYTES].len);
  }

cleanup:

  if(aes) {
    BCryptCloseAlgorithmProvider(aes,0);
  }

  if (ctx) {
    BCryptDestroyKey(ctx);
  }

  if(key_object) {
    HeapFree(GetProcessHeap(), 0, key_object);
  }

  return res;
}
Example #6
0
int main(int argc, char **argv)
{
    // Handles for RSA
    BCRYPT_ALG_HANDLE hAlgo = NULL;
    BCRYPT_KEY_HANDLE hKey = NULL;

    FILE_CRYPTO_INFO cryptoInfo;
    PBYTE psPlainText = NULL;
    DWORD dwBytesWritten = 0;
    DWORD dwBytesRead = 0;
    CCRYPT_STATUS status;

    // TEST DATA //
    PBYTE pbData1 = "Hello world!\n";
    PBYTE pbData2 = "Hello person!\n";
    PBYTE pbData3 = "This is cool!\n";
    
    if (argc != 2) {
        printf("USAGE: %s <encrypt|decrypt>\n\n", argv[0]);
        return -1;
    }

    // --------------------------------------------------------------------------
    //
    //  Testing encrypting/writing to file
    //
    // --------------------------------------------------------------------------

    if (strcmp(argv[1], "encrypt") == 0)
    {
        if (CCRYPT_STATUS_SUCCESS != (status = CCryptCreateFile(&cryptoInfo, TEXT("test.log"), CCRYPT_FILE_WRITE))) {
            printf("CCryptCreateFile error: %x\n", status);
            return -1;
        }

        // Write data to file
        if (!CCryptWriteFile(&cryptoInfo, pbData1, strlen(pbData1), &dwBytesWritten)) {
            printf("CCryptWriteFile error: %x\n", GetLastError());
            return -1;
        }
        if (!CCryptWriteFile(&cryptoInfo, pbData2, strlen(pbData2), &dwBytesWritten)) {
            printf("CCryptWriteFile error: %x\n", GetLastError());
            return -1;
        }
        if (!CCryptWriteFile(&cryptoInfo, pbData3, strlen(pbData3), &dwBytesWritten)) {
            printf("CCryptWriteFile error: %x\n", GetLastError());
            return -1;
        }

        // Import our RSA public key to encrypt AES key
        if (CCRYPT_STATUS_SUCCESS != (status = RSAImportKey(&hAlgo, &hKey, TEXT("public.key"), BCRYPT_RSAPUBLIC_BLOB))) {
            printf("RSAImportKey error (public): %x\n", status);
            return -1;
        }

        // Finalize the file write
        if (!CCryptFinalizeFile(&cryptoInfo, hKey)) {
            printf("CCryptFinalizeFile error: %d\n", GetLastError());
            return -1;
        }

        CCryptCloseHandle(&cryptoInfo);
        BCryptDestroyKey(hKey);
        BCryptCloseAlgorithmProvider(hAlgo, 0);
    }

    // --------------------------------------------------------------------------
    //
    //  Testing reading/decrypting from file
    //
    // --------------------------------------------------------------------------

    else
    {
        if (CCRYPT_STATUS_SUCCESS != (status = CCryptCreateFile(&cryptoInfo, TEXT("test.log"), CCRYPT_FILE_READ))) {
            printf("CCryptCreateFile error: %x\n", status);
            return -1;
        }

        // Import our RSA private key to decrypt AES key
        if (CCRYPT_STATUS_SUCCESS != (status = RSAImportKey(&hAlgo, &hKey, TEXT("private.key"), BCRYPT_RSAPRIVATE_BLOB))) {
            printf("RSAImportKey error (private): %x\n", status);
            return -1;
        }

        if (!CCryptReadFile(&cryptoInfo, hKey, &psPlainText, &dwBytesRead))
        {
            printf("CCryptReadFile error: %x\n", GetLastError());
            return -1;
        }

        printf("Plain text: %s\n\n", psPlainText);

        if (psPlainText != NULL) {
            HeapFree(GetProcessHeap(), 0, psPlainText);
        }

        CCryptCloseHandle(&cryptoInfo);
        BCryptDestroyKey(hKey);
        BCryptCloseAlgorithmProvider(hAlgo, 0);
    }
    
    return 0;
}
Example #7
0
int
_libssh2_wincng_rsa_new_private(libssh2_rsa_ctx **rsa,
                                LIBSSH2_SESSION *session,
                                const char *filename,
                                const unsigned char *passphrase)
{
#ifdef HAVE_LIBCRYPT32
    BCRYPT_KEY_HANDLE hKey;
    unsigned char *pbEncoded, *pbStructInfo;
    unsigned long cbEncoded, cbStructInfo;
    int ret;

    (void)session;

    ret = _libssh2_wincng_load_private(session, filename,
                                       (const char *)passphrase,
                                       &pbEncoded, &cbEncoded);
    if (ret) {
        return -1;
    }

    ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded,
                                     PKCS_RSA_PRIVATE_KEY,
                                     &pbStructInfo, &cbStructInfo);

    free(pbEncoded);

    if (ret) {
        return -1;
    }


    ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL,
                              LEGACY_RSAPRIVATE_BLOB, &hKey,
                              pbStructInfo, cbStructInfo, 0);
    if (!BCRYPT_SUCCESS(ret)) {
        free(pbStructInfo);
        return -1;
    }


    *rsa = malloc(sizeof(libssh2_rsa_ctx));
    if (!(*rsa)) {
        BCryptDestroyKey(hKey);
        free(pbStructInfo);
        return -1;
    }

    (*rsa)->hKey = hKey;
    (*rsa)->pbKeyObject = pbStructInfo;
    (*rsa)->cbKeyObject = cbStructInfo;

    return 0;
#else
    (void)rsa;
    (void)filename;
    (void)passphrase;

    return _libssh2_error(session, LIBSSH2_ERROR_FILE,
                          "Unable to load RSA key from private key file: "
                          "Method unsupported in Windows CNG backend");
#endif /* HAVE_LIBCRYPT32 */
}
Example #8
0
int
_libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa,
                        const unsigned char *edata,
                        unsigned long elen,
                        const unsigned char *ndata,
                        unsigned long nlen,
                        const unsigned char *ddata,
                        unsigned long dlen,
                        const unsigned char *pdata,
                        unsigned long plen,
                        const unsigned char *qdata,
                        unsigned long qlen,
                        const unsigned char *e1data,
                        unsigned long e1len,
                        const unsigned char *e2data,
                        unsigned long e2len,
                        const unsigned char *coeffdata,
                        unsigned long coefflen)
{
    BCRYPT_KEY_HANDLE hKey;
    BCRYPT_RSAKEY_BLOB *rsakey;
    LPCWSTR lpszBlobType;
    unsigned char *key;
    unsigned long keylen, offset, mlen, p1len = 0, p2len = 0;
    int ret;

    mlen = max(_libssh2_wincng_bn_size(ndata, nlen),
               _libssh2_wincng_bn_size(ddata, dlen));
    offset = sizeof(BCRYPT_RSAKEY_BLOB);
    keylen = offset + elen + mlen;
    if (ddata && dlen > 0) {
        p1len = max(_libssh2_wincng_bn_size(pdata, plen),
                    _libssh2_wincng_bn_size(e1data, e1len));
        p2len = max(_libssh2_wincng_bn_size(qdata, qlen),
                    _libssh2_wincng_bn_size(e2data, e2len));
        keylen += p1len * 3 + p2len * 2 + mlen;
    }

    key = malloc(keylen);
    if (!key) {
        return -1;
    }

    memset(key, 0, keylen);


    /* http://msdn.microsoft.com/library/windows/desktop/aa375531.aspx */
    rsakey = (BCRYPT_RSAKEY_BLOB *)key;
    rsakey->BitLength = mlen * 8;
    rsakey->cbPublicExp = elen;
    rsakey->cbModulus = mlen;

    memcpy(key + offset, edata, elen);
    offset += elen;

    if (nlen < mlen)
        memcpy(key + offset + mlen - nlen, ndata, nlen);
    else
        memcpy(key + offset, ndata + nlen - mlen, mlen);

    if (ddata && dlen > 0) {
        offset += mlen;

        if (plen < p1len)
            memcpy(key + offset + p1len - plen, pdata, plen);
        else
            memcpy(key + offset, pdata + plen - p1len, p1len);
        offset += p1len;

        if (qlen < p2len)
            memcpy(key + offset + p2len - qlen, qdata, qlen);
        else
            memcpy(key + offset, qdata + qlen - p2len, p2len);
        offset += p2len;

        if (e1len < p1len)
            memcpy(key + offset + p1len - e1len, e1data, e1len);
        else
            memcpy(key + offset, e1data + e1len - p1len, p1len);
        offset += p1len;

        if (e2len < p2len)
            memcpy(key + offset + p2len - e2len, e2data, e2len);
        else
            memcpy(key + offset, e2data + e2len - p2len, p2len);
        offset += p2len;

        if (coefflen < p1len)
            memcpy(key + offset + p1len - coefflen, coeffdata, coefflen);
        else
            memcpy(key + offset, coeffdata + coefflen - p1len, p1len);
        offset += p1len;

        if (dlen < mlen)
            memcpy(key + offset + mlen - dlen, ddata, dlen);
        else
            memcpy(key + offset, ddata + dlen - mlen, mlen);

        lpszBlobType = BCRYPT_RSAFULLPRIVATE_BLOB;
        rsakey->Magic = BCRYPT_RSAFULLPRIVATE_MAGIC;
        rsakey->cbPrime1 = p1len;
        rsakey->cbPrime2 = p2len;
    } else {
        lpszBlobType = BCRYPT_RSAPUBLIC_BLOB;
        rsakey->Magic = BCRYPT_RSAPUBLIC_MAGIC;
        rsakey->cbPrime1 = 0;
        rsakey->cbPrime2 = 0;
    }


    ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL, lpszBlobType,
                              &hKey, key, keylen, 0);
    if (!BCRYPT_SUCCESS(ret)) {
        free(key);
        return -1;
    }


    *rsa = malloc(sizeof(libssh2_rsa_ctx));
    if (!(*rsa)) {
        BCryptDestroyKey(hKey);
        free(key);
        return -1;
    }

    (*rsa)->hKey = hKey;
    (*rsa)->pbKeyObject = key;
    (*rsa)->cbKeyObject = keylen;

    return 0;
}
Example #9
0
int
_libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
                               _libssh2_bn *a,
                               _libssh2_bn *p,
                               _libssh2_bn *m,
                               _libssh2_bn_ctx *bnctx)
{
    BCRYPT_KEY_HANDLE hKey;
    BCRYPT_RSAKEY_BLOB *rsakey;
    unsigned char *key, *bignum;
    unsigned long keylen, offset, length;
    int ret;

    (void)bnctx;

    if (!r || !a || !p || !m)
        return -1;

    offset = sizeof(BCRYPT_RSAKEY_BLOB);
    keylen = offset + p->length + m->length;

    key = malloc(keylen);
    if (!key)
        return -1;


    /* http://msdn.microsoft.com/library/windows/desktop/aa375531.aspx */
    rsakey = (BCRYPT_RSAKEY_BLOB *)key;
    rsakey->Magic = BCRYPT_RSAPUBLIC_MAGIC;
    rsakey->BitLength = m->length * 8;
    rsakey->cbPublicExp = p->length;
    rsakey->cbModulus = m->length;
    rsakey->cbPrime1 = 0;
    rsakey->cbPrime2 = 0;

    memcpy(key + offset, p->bignum, p->length);
    offset += p->length;

    memcpy(key + offset, m->bignum, m->length);

    ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL,
                              BCRYPT_RSAPUBLIC_BLOB, &hKey, key, keylen,
                              BCRYPT_NO_KEY_VALIDATION);

    if (BCRYPT_SUCCESS(ret)) {
        ret = BCryptEncrypt(hKey, a->bignum, a->length, NULL, NULL, 0,
                            NULL, 0, &length, BCRYPT_PAD_NONE);
        if (BCRYPT_SUCCESS(ret)) {
            if (!_libssh2_wincng_bignum_resize(r, length)) {
                length = max(a->length, length);
                bignum = malloc(length);
                if (bignum) {
                    offset = length - a->length;
                    memset(bignum, 0, offset);
                    memcpy(bignum + offset, a->bignum, a->length);

                    ret = BCryptEncrypt(hKey, bignum, length, NULL, NULL, 0,
                                        r->bignum, r->length, &offset,
                                        BCRYPT_PAD_NONE);

                    free(bignum);

                    if (BCRYPT_SUCCESS(ret)) {
                        _libssh2_wincng_bignum_resize(r, offset);
                    }
                } else
                    ret = STATUS_NO_MEMORY;
            } else
                ret = STATUS_NO_MEMORY;
        }

        BCryptDestroyKey(hKey);
    }

    free(key);

    return BCRYPT_SUCCESS(ret) ? 0 : -1;
}
Example #10
0
int
_libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx,
                            _libssh2_cipher_type(type),
                            unsigned char *iv,
                            unsigned char *secret,
                            int encrypt)
{
    BCRYPT_KEY_HANDLE hKey;
    BCRYPT_KEY_DATA_BLOB_HEADER *header;
    unsigned char *pbKeyObject, *pbIV, *key;
    unsigned long dwKeyObject, dwIV, dwBlockLength, cbData, keylen;
    int ret;

    (void)encrypt;

    ret = BCryptGetProperty(*type.phAlg, BCRYPT_OBJECT_LENGTH,
                            (unsigned char *)&dwKeyObject,
                            sizeof(dwKeyObject),
                            &cbData, 0);
    if (!BCRYPT_SUCCESS(ret)) {
        return -1;
    }

    ret = BCryptGetProperty(*type.phAlg, BCRYPT_BLOCK_LENGTH,
                            (unsigned char *)&dwBlockLength,
                            sizeof(dwBlockLength),
                            &cbData, 0);
    if (!BCRYPT_SUCCESS(ret)) {
        return -1;
    }

    pbKeyObject = malloc(dwKeyObject);
    if (!pbKeyObject) {
        return -1;
    }


    keylen = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + type.dwKeyLength;
    key = malloc(keylen);
    if (!key) {
        free(pbKeyObject);
        return -1;
    }


    header = (BCRYPT_KEY_DATA_BLOB_HEADER *)key;
    header->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
    header->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
    header->cbKeyData = type.dwKeyLength;

    memcpy(key + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER),
           secret, type.dwKeyLength);

    ret = BCryptImportKey(*type.phAlg, NULL, BCRYPT_KEY_DATA_BLOB, &hKey,
                          pbKeyObject, dwKeyObject, key, keylen, 0);

    free(key);

    if (!BCRYPT_SUCCESS(ret)) {
        free(pbKeyObject);
        return -1;
    }

    if (type.dwUseIV) {
        pbIV = malloc(dwBlockLength);
        if (!pbIV) {
            BCryptDestroyKey(hKey);
            free(pbKeyObject);
            return -1;
        }
        dwIV = dwBlockLength;
        memcpy(pbIV, iv, dwIV);
    } else {
        pbIV = NULL;
        dwIV = 0;
    }


    ctx->hKey = hKey;
    ctx->pbKeyObject = pbKeyObject;
    ctx->pbIV = pbIV;
    ctx->dwKeyObject = dwKeyObject;
    ctx->dwIV = dwIV;
    ctx->dwBlockLength = dwBlockLength;

    return 0;
}
Example #11
0
int
_libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa,
                        const unsigned char *pdata,
                        unsigned long plen,
                        const unsigned char *qdata,
                        unsigned long qlen,
                        const unsigned char *gdata,
                        unsigned long glen,
                        const unsigned char *ydata,
                        unsigned long ylen,
                        const unsigned char *xdata,
                        unsigned long xlen)
{
    BCRYPT_KEY_HANDLE hKey;
    BCRYPT_DSA_KEY_BLOB *dsakey;
    LPCWSTR lpszBlobType;
    unsigned char *key;
    unsigned long keylen, offset, length;
    int ret;

    length = max(max(_libssh2_wincng_bn_size(pdata, plen),
                     _libssh2_wincng_bn_size(gdata, glen)),
                 _libssh2_wincng_bn_size(ydata, ylen));
    offset = sizeof(BCRYPT_DSA_KEY_BLOB);
    keylen = offset + length * 3;
    if (xdata && xlen > 0)
        keylen += 20;

    key = malloc(keylen);
    if (!key) {
        return -1;
    }

    memset(key, 0, keylen);


    /* http://msdn.microsoft.com/library/windows/desktop/aa833126.aspx */
    dsakey = (BCRYPT_DSA_KEY_BLOB *)key;
    dsakey->cbKey = length;

    memset(dsakey->Count, -1, sizeof(dsakey->Count));
    memset(dsakey->Seed, -1, sizeof(dsakey->Seed));

    if (qlen < 20)
        memcpy(dsakey->q + 20 - qlen, qdata, qlen);
    else
        memcpy(dsakey->q, qdata + qlen - 20, 20);

    if (plen < length)
        memcpy(key + offset + length - plen, pdata, plen);
    else
        memcpy(key + offset, pdata + plen - length, length);
    offset += length;

    if (glen < length)
        memcpy(key + offset + length - glen, gdata, glen);
    else
        memcpy(key + offset, gdata + glen - length, length);
    offset += length;

    if (ylen < length)
        memcpy(key + offset + length - ylen, ydata, ylen);
    else
        memcpy(key + offset, ydata + ylen - length, length);

    if (xdata && xlen > 0) {
        offset += length;

        if (xlen < 20)
            memcpy(key + offset + 20 - xlen, xdata, xlen);
        else
            memcpy(key + offset, xdata + xlen - 20, 20);

        lpszBlobType = BCRYPT_DSA_PRIVATE_BLOB;
        dsakey->dwMagic = BCRYPT_DSA_PRIVATE_MAGIC;
    } else {
        lpszBlobType = BCRYPT_DSA_PUBLIC_BLOB;
        dsakey->dwMagic = BCRYPT_DSA_PUBLIC_MAGIC;
    }


    ret = BCryptImportKeyPair(_libssh2_wincng.hAlgDSA, NULL, lpszBlobType,
                              &hKey, key, keylen, 0);
    if (!BCRYPT_SUCCESS(ret)) {
        free(key);
        return -1;
    }


    *dsa = malloc(sizeof(libssh2_dsa_ctx));
    if (!(*dsa)) {
        BCryptDestroyKey(hKey);
        free(key);
        return -1;
    }

    (*dsa)->hKey = hKey;
    (*dsa)->pbKeyObject = key;
    (*dsa)->cbKeyObject = keylen;

    return 0;
}
/*****************************************************************************
 HrVerify

 This sample demontrates XML signature verification

*****************************************************************************/
HRESULT
HrVerify(
    LPCWSTR         wszFileIn
    )
{
    HRESULT     hr = S_FALSE;
    HCRYPTXML   hDoc = NULL;
    ULONG       i;
    const CRYPT_XML_DOC_CTXT  *pDoc = NULL;
    const CRYPT_XML_SIGNATURE *pSig = NULL;
    const CRYPT_XML_REFERENCE *pRef = NULL;

    CRYPT_XML_STATUS    Status = {0};

    BCRYPT_KEY_HANDLE   hKey = NULL;
    BCRYPT_KEY_HANDLE   hKeyAlloc = NULL;   // BCryptDestroyKey
    PCCERT_CONTEXT      pCert = NULL;

    CRYPT_XML_DATA_PROVIDER DataProvider = {0};

    CRYPT_XML_BLOB   Encoded = { CRYPT_XML_CHARSET_AUTO, 0, NULL };

    hr = HrLoadFile(
                                        wszFileIn,
                                        &Encoded.pbData,
                                        &Encoded.cbData
                                        );
    if( FAILED(hr) )
    {
        goto CleanUp;
    }

    hr = CryptXmlOpenToDecode(
                                        NULL,               // no custom transforms
                                        0,
                                        NULL,
                                        0,
                                        &Encoded,
                                        &hDoc
                                        );
    if( FAILED(hr) )
    {
        goto CleanUp;
    }

    hr = CryptXmlGetDocContext( 
                                        hDoc, 
                                        &pDoc 
                                        );
    if( FAILED(hr) )
    {
        goto CleanUp;
    }

    if( pDoc->cSignature < 1 )
    {
        wprintf( L"WARNING: The document contains no Signature element.\r\n" );

        // No signatures found
        hr = S_FALSE;
        goto CleanUp;
    }

    for( i=0; i<pDoc->cSignature; i++ )
    {
        hKey = NULL;
        if( NULL == hKeyAlloc )
        {
            BCryptDestroyKey( hKeyAlloc );
            hKeyAlloc = NULL;
        }

        //
        // Find Signer's certificate
        //

        for( ULONG ki=0; ki<pDoc->rgpSignature[i]->pKeyInfo->cKeyInfo && NULL == hKey; ki++ )
        {
            if( CRYPT_XML_KEYINFO_TYPE_X509DATA ==
                pDoc->rgpSignature[i]->pKeyInfo->rgKeyInfo[ki].dwType )
            {
                for( ULONG x=0; x<pDoc->rgpSignature[i]->pKeyInfo->rgKeyInfo[ki].X509Data.cX509Data; x++ )
                {
                    CRYPT_XML_X509DATA_ITEM *pX = &pDoc->rgpSignature[i]->pKeyInfo->rgKeyInfo[ki].X509Data.rgX509Data[x];
                    if( CRYPT_XML_X509DATA_TYPE_CERTIFICATE == pX->dwType )
                    {
                        //
                        // SAMPLE: Just assume that the first cert is the one ...
                        //         In production code, implement the full logic
                        //          to find the signer's cert, from a set of multiple X.509 data elements
                        //
                        
                        pCert = CertCreateCertificateContext( 
                                        X509_ASN_ENCODING,
                                        pX->Certificate.pbData,
                                        pX->Certificate.cbData
                                        );

                        if( NULL != pCert )
                        {
                            if( CryptImportPublicKeyInfoEx2(
                                        X509_ASN_ENCODING,
                                        &pCert->pCertInfo->SubjectPublicKeyInfo,
                                        CRYPT_OID_INFO_PUBKEY_SIGN_KEY_FLAG,
                                        NULL,
                                        &hKeyAlloc 
                                        ))
                            {
                                hKey = hKeyAlloc;
                                break;
                            }
                        }
                    }
                }
            }
        }

        if( NULL == hKey )
        {
            wprintf( L"ERROR: Unable to find signer's key to verify signature [%d] Id='%s'\r\n",  
                        i,
                        pDoc->rgpSignature[i]->wszId 
                        );

            hr = CRYPT_XML_E_SIGNER;
            goto CleanUp;
        }

        //
        // SAMPLE: Verify Signer's Trust
        //
        {
            //
            // TODO: Use CertGetCertificateChain() to build the chain and verify the trust.
            //
            
            //
            // TODO: Accept only strong cryptographic algorithms and key strengths.
            // Also, place max key length on key size to avoid Denial of Service (DoS)
            // attacks on verification key operations. 
            //
        }

        hr = CryptXmlVerifySignature(
                                        pDoc->rgpSignature[i]->hSignature,
                                        hKey,
                                        0
                                        );
        if( FAILED(hr) )
        {
            wprintf( L"FAIL: CryptXmlVerifySignature() returned 0x%08x error on signature [%d] Id='%s'\r\n",  
                        hr,
                        i,
                        pDoc->rgpSignature[i]->wszId 
                        );
            goto CleanUp;
        }

        wprintf( L"Signature Value on signature [%d] Id='%s' is valid.\r\n",  
                        i,
                        pDoc->rgpSignature[i]->wszId 
                        );

        //
        // Verify References
        //

        hr = CryptXmlGetSignature(
                                        pDoc->rgpSignature[i]->hSignature,
                                        &pSig
                                        );
        if( FAILED(hr) )
        {
            goto CleanUp;
        }

        for( ULONG r=0; r<pSig->SignedInfo.cReference; r++ )
        {
            hr = CryptXmlGetReference(
                                        pSig->SignedInfo.rgpReference[r]->hReference,
                                        &pRef
                                        );
            if( FAILED(hr) )
            {
                goto CleanUp;
            }

            hr = CryptXmlGetStatus(
                                        pSig->SignedInfo.rgpReference[r]->hReference,
                                        &Status
                                        );
            if( FAILED(hr) )
            {
                goto CleanUp;
            }

            if( 0 != ( Status.dwErrorStatus & CRYPT_XML_STATUS_ERROR_NOT_RESOLVED ))
            {
                //
                // Resolve the external references only.
                // The internal references was resolved by CryptXml during CryptXmlVerifySignature
                //

                if( 0 == ( Status.dwInfoStatus & CRYPT_XML_STATUS_INTERNAL_REFERENCE ))
                {
                    //
                    // TODO:  Verify the scope of the Reference Target URI prior to resolving 
                    //

                    hr = HrSampleResolveExternalXmlReference(
                                        pRef->wszUri,
                                        &DataProvider
                                        );
                    if( FAILED(hr) )
                    {
                        goto CleanUp;
                    }
                }

                if( NULL == DataProvider.pfnRead )
                {
                    hr = CRYPT_XML_E_UNRESOLVED_REFERENCE;
                    goto CleanUp;
                }

                //
                // Provider must be released by the callee
                //

                hr = CryptXmlDigestReference(
                                        pSig->SignedInfo.rgpReference[r]->hReference,
                                        0,
                                        &DataProvider
                                        );

                ZeroMemory( &DataProvider, sizeof DataProvider );

                //
                // Get the status to check it again
                //

                hr = CryptXmlGetStatus(
                                        pSig->SignedInfo.rgpReference[r]->hReference,
                                        &Status
                                        );
            }

            if( 0 != ( Status.dwErrorStatus & CRYPT_XML_STATUS_ERROR_DIGEST_INVALID ))
            {
                wprintf( L"Digest Value on reference[%d] Id='%s' is not valid.\r\n",  
                                        r,
                                        pSig->SignedInfo.rgpReference[r]->wszId );
            }
            else
            {
                if( 0 != ( Status.dwErrorStatus & CRYPT_XML_STATUS_ERROR_NOT_RESOLVED ))
                {
                    wprintf( L"Reference[%d] Id='%s' is not resolved\r\n",  
                                        r,
                                        pSig->SignedInfo.rgpReference[r]->wszId );
                }
                else
                {
                    wprintf( L"Digest Value on reference[%d] Id='%s' is valid\r\n",  
                                        r,
                                        pSig->SignedInfo.rgpReference[r]->wszId );
                }
            }
        }

        //
        // Average status on the Signature
        //

        hr = CryptXmlGetStatus( pDoc->rgpSignature[i]->hSignature, &Status );
        if( FAILED(hr) )
        {
            goto CleanUp;
        }

        if( 0 != ( Status.dwErrorStatus & CRYPT_XML_STATUS_ERROR_DIGEST_INVALID ))
        {
            hr = CRYPT_XML_E_INVALID_DIGEST;
            goto CleanUp;
        }

        if( 0 != ( Status.dwErrorStatus & CRYPT_XML_STATUS_ERROR_NOT_RESOLVED ))
        {
            hr = CRYPT_XML_E_UNRESOLVED_REFERENCE;
            goto CleanUp;
        }
    }

    hr = S_OK;

CleanUp:

    if( NULL != Encoded.pbData )
    {
        LocalFree( Encoded.pbData );
    }

    if( NULL == hKeyAlloc )
    {
        BCryptDestroyKey( hKeyAlloc );
    }

    if( NULL != pCert )
    {
        CertFreeCertificateContext( pCert );
    }

    return hr;
}
Example #13
0
UINT SfDecryptPayload(
	LPWSTR lpParameter
	)
{
	BOOL                cond = FALSE, bSuccess = FALSE;
	PBYTE               cng_object, hashdata, decrypted, enc_data, extracted;
	ULONG               obj_sz, rlen, hdatasz, enc_data_size;
	BCRYPT_ALG_HANDLE   h_alg = NULL;
	BCRYPT_HASH_HANDLE  h_hash = NULL;
	BCRYPT_KEY_HANDLE   h_rc4key = NULL;
	NTSTATUS            status;
	HANDLE              pheap = NULL;
	PIMAGE_FILE_HEADER  fheader;
	PVOID               pdll = NULL;
	WCHAR               InputFile[MAX_PATH + 1], OutputFile[MAX_PATH + 1];

	rlen = 0;
	RtlSecureZeroMemory(InputFile, sizeof(InputFile));
	GetCommandLineParam(lpParameter, 1, InputFile, MAX_PATH, &rlen);
	if (rlen == 0) {
		SfcuiPrintText(g_ConOut,
			T_SFDECRYPTUSAGE,
			g_ConsoleOutput, FALSE);
		return (UINT)-1;
	}

	do {

		rlen = 0;
		GetCommandLineParam(lpParameter, 2, OutputFile, MAX_PATH, &rlen);
		
		if (rlen == 0)
			_strcpy(OutputFile, TEXT("out.bin"));
		
		pdll = SfuCreateFileMappingNoExec(InputFile);
		if (pdll == NULL)
			break;

		enc_data_size = 0;
		enc_data = SfuQueryResourceData(2, pdll, &enc_data_size);
		if (enc_data == NULL)
			break;

		fheader = &(RtlImageNtHeader(pdll)->FileHeader);

		status = BCryptOpenAlgorithmProvider(&h_alg, BCRYPT_MD5_ALGORITHM, NULL, 0);
		if (!NT_SUCCESS(status))
			break;
		obj_sz = 0;
		rlen = 0;
		status = BCryptGetProperty(h_alg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&obj_sz, sizeof(obj_sz), &rlen, 0);
		if (!NT_SUCCESS(status))
			break;

		hdatasz = 0;
		rlen = 0;
		status = BCryptGetProperty(h_alg, BCRYPT_HASH_LENGTH, (PUCHAR)&hdatasz, sizeof(hdatasz), &rlen, 0);
		if (!NT_SUCCESS(status))
			break;

		pheap = HeapCreate(0, 0, 0);
		if (pheap == NULL)
			break;

		cng_object = HeapAlloc(pheap, HEAP_ZERO_MEMORY, obj_sz);
		if (cng_object == NULL)
			break;

		hashdata = HeapAlloc(pheap, HEAP_ZERO_MEMORY, hdatasz);
		if (hashdata == NULL)
			break;

		status = BCryptCreateHash(h_alg, &h_hash, cng_object, obj_sz, NULL, 0, 0);
		if (!NT_SUCCESS(status))
			break;

		status = BCryptHashData(h_hash, (PUCHAR)fheader, sizeof(IMAGE_FILE_HEADER), 0);
		if (!NT_SUCCESS(status))
			break;

		status = BCryptFinishHash(h_hash, hashdata, hdatasz, 0);
		if (!NT_SUCCESS(status))
			break;

		BCryptDestroyHash(h_hash);
		BCryptCloseAlgorithmProvider(h_alg, 0);
		HeapFree(pheap, 0, cng_object);
		h_alg = NULL;
		h_hash = NULL;

		status = BCryptOpenAlgorithmProvider(&h_alg, BCRYPT_RC4_ALGORITHM, NULL, 0);
		if (!NT_SUCCESS(status))
			break;

		obj_sz = 0;
		rlen = 0;
		status = BCryptGetProperty(h_alg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&obj_sz, sizeof(obj_sz), &rlen, 0);
		if (!NT_SUCCESS(status))
			break;

		cng_object = HeapAlloc(pheap, HEAP_ZERO_MEMORY, obj_sz);
		if (cng_object == NULL)
			break;

		status = BCryptGenerateSymmetricKey(h_alg, &h_rc4key, cng_object, obj_sz, hashdata, hdatasz, 0);
		if (!NT_SUCCESS(status))
			break;

		decrypted = HeapAlloc(pheap, HEAP_ZERO_MEMORY, enc_data_size);
		if (decrypted == NULL)
			break;

		rlen = 0;
		status = BCryptEncrypt(h_rc4key, enc_data, enc_data_size, NULL, NULL, 0, decrypted, enc_data_size, &rlen, 0);
		if (!NT_SUCCESS(status))
			break;

		bSuccess = FALSE;
		enc_data_size = rlen;
		rlen = 0;
		extracted = SfcabExtractMemory(decrypted, enc_data_size, &rlen);
		if (extracted) {

			if (SfuWriteBufferToFile(OutputFile, extracted, rlen, FALSE, FALSE) == rlen) {
				bSuccess = TRUE;
			}
			LocalFree(extracted);
		}
		else {
			//failed to extract, drop cab as is
			if (SfuWriteBufferToFile(OutputFile, decrypted, enc_data_size, FALSE, FALSE) == enc_data_size) {
				bSuccess = TRUE;
			}
		}

		if (bSuccess) {

			SfcuiPrintText(g_ConOut,
				T_SFDECRYPTED,
				g_ConsoleOutput, FALSE);

			SfcuiPrintText(g_ConOut,
				OutputFile,
				g_ConsoleOutput, FALSE);
		}

	} while (cond);

	if (bSuccess == FALSE) {

		SfcuiPrintText(g_ConOut,
			T_SFDECRYPTFAIL,
			g_ConsoleOutput, FALSE);
		
	}

	if (h_rc4key != NULL)
		BCryptDestroyKey(h_rc4key);

	if (h_hash != NULL)
		BCryptDestroyHash(h_hash);

	if (h_alg != NULL)
		BCryptCloseAlgorithmProvider(h_alg, 0);

	if (pheap != NULL)
		HeapDestroy(pheap);

	if (pdll != 0)
		NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)pdll);

	return 0;
}
//----------------------------------------------------------------------------
//
// PerformKeyDerivation
//
//----------------------------------------------------------------------------
NTSTATUS
PeformKeyDerivation(
    _In_  DWORD    ArrayIndex
    )
{
    NTSTATUS            Status;
    BCRYPT_ALG_HANDLE   KdfAlgHandle = NULL;
    BCRYPT_KEY_HANDLE   SecretKeyHandle = NULL;
    
    DWORD   ResultLength = 0;
    PBYTE   DerivedKey = NULL;
    DWORD   DerivedKeyLength = 0;
  
    
    Status = BCryptOpenAlgorithmProvider(
                                        &KdfAlgHandle,              // Alg Handle pointer
                                        KdfAlgorithmNameArray[ArrayIndex],   
                                                                    // Cryptographic Algorithm name (null terminated unicode string)
                                        NULL,                       // Provider name; if null, the default provider is loaded
                                        0);                         // Flags
        if( !NT_SUCCESS(Status) )
        {
            ReportError(Status);
            goto cleanup;
        }
        
        Status = BCryptGenerateSymmetricKey(
                                        KdfAlgHandle,               // Algorithm Handle 
                                        &SecretKeyHandle,           // A pointer to a key handle
                                        NULL,                       // Buffer that recieves the key object;NULL implies memory is allocated and freed by the function
                                        0,                          // Size of the buffer in bytes
                                        (PBYTE) Secret,             // Buffer that contains the key material
                                        sizeof(Secret),             // Size of the buffer in bytes
                                        0);                         // Flags
        if( !NT_SUCCESS(Status) )
        {
            ReportError(Status);
            goto cleanup;
        }
        
        //
        // Derive the key
        //
        
        DerivedKeyLength = DERIVED_KEY_LEN;
        
        DerivedKey = (PBYTE)HeapAlloc(GetProcessHeap(), 0, DerivedKeyLength);
        if( NULL == DerivedKey )
        {
            Status = STATUS_NO_MEMORY;
            ReportError(Status);
            goto cleanup;
        }

        // Generic parameters: 
        // KDF_GENERIC_PARAMETER and KDF_HASH_ALGORITHM are the generic parameters that can be passed for the following KDF algorithms:
        // BCRYPT_SP800108_CTR_HMAC_ALGORITHM 
        //      KDF_GENERIC_PARAMETER = KDF_LABEL||0x00||KDF_CONTEXT 
        // BCRYPT_SP80056A_CONCAT_ALGORITHM
        //      KDF_GENERIC_PARAMETER = KDF_ALGORITHMID || KDF_PARTYUINFO || KDF_PARTYVINFO {|| KDF_SUPPPUBINFO } {|| KDF_SUPPPRIVINFO }
        // BCRYPT_PBKDF2_ALGORITHM
        //      KDF_GENERIC_PARAMETER = KDF_SALT
        // BCRYPT_CAPI_KDF_ALGORITHM
        //      KDF_GENERIC_PARAMETER = Not used
        //
        // Alternatively, KDF specific parameters can be passed.
        // For BCRYPT_SP800108_CTR_HMAC_ALGORITHM: 
        //      KDF_HASH_ALGORITHM, KDF_LABEL and KDF_CONTEXT are required
        // For BCRYPT_SP80056A_CONCAT_ALGORITHM:
        //      KDF_HASH_ALGORITHM, KDF_ALGORITHMID, KDF_PARTYUINFO, KDF_PARTYVINFO are required
        //      KDF_SUPPPUBINFO, KDF_SUPPPRIVINFO are optional
        // For BCRYPT_PBKDF2_ALGORITHM
        //      KDF_HASH_ALGORITHM is required
        //      KDF_ITERATION_COUNT, KDF_SALT are optional
        //      Iteration count, (if not specified) will default to 10,000
        // For BCRYPT_CAPI_KDF_ALGORITHM
        //      KDF_HASH_ALGORITHM is required
        //
       
        // 
        // This sample uses KDF specific parameters defined in KeyDerivation.h
        //

        Status = BCryptKeyDerivation(
                                        SecretKeyHandle,            // Handle to the password key
                                        &ParamList[ArrayIndex],     // Parameters to the KDF algorithm
                                        DerivedKey,                 // Address of the buffer which recieves the derived bytes
                                        DerivedKeyLength,           // Size of the buffer in bytes
                                        &ResultLength,              // Variable that recieves number of bytes copied to above buffer 
                                        0);                         // Flags
        if( !NT_SUCCESS(Status) )
        {
            ReportError(Status);
            goto cleanup;
        }

        //
        // DerivedKeyLength bytes have been derived
        //

cleanup:    
   
        if( NULL != DerivedKey )
        {
            HeapFree( GetProcessHeap(), 0, DerivedKey);
            DerivedKey = NULL;
        }

        if( NULL != SecretKeyHandle )
        {
            Status = BCryptDestroyKey(SecretKeyHandle);
            if( !NT_SUCCESS(Status) )
            {
                ReportError(Status);
            }
            SecretKeyHandle = NULL;
        }

        if( NULL != KdfAlgHandle )
        {
            Status = BCryptCloseAlgorithmProvider(KdfAlgHandle,0);
            if( !NT_SUCCESS(Status) )
            {
                ReportError(Status);
            }
            KdfAlgHandle = NULL;
        }

    return Status;

}