static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const char *contname, char *provname, DWORD ptype, DWORD keyspec) { CAPI_KEY *key; key = OPENSSL_malloc(sizeof(CAPI_KEY)); CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n", contname, provname, ptype); if (!CryptAcquireContextA(&key->hprov, contname, provname, ptype, 0)) { CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); capi_addlasterror(); goto err; } if (!CryptGetUserKey(key->hprov, keyspec, &key->key)) { CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR); capi_addlasterror(); CryptReleaseContext(key->hprov, 0); goto err; } key->keyspec = keyspec; key->pcert = NULL; return key; err: OPENSSL_free(key); return NULL; }
int capi_rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { int i; unsigned char *tmpbuf; CAPI_KEY *capi_key; CAPI_CTX *ctx; ctx = ENGINE_get_ex_data(rsa->engine, capi_idx); CAPI_trace(ctx, "Called capi_rsa_priv_dec()\n"); capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); if (!capi_key) { CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_CANT_GET_KEY); return -1; } if(padding != RSA_PKCS1_PADDING) { char errstr[10]; BIO_snprintf(errstr, 10, "%d", padding); CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_UNSUPPORTED_PADDING); ERR_add_error_data(2, "padding=", errstr); return -1; } /* Create temp reverse order version of input */ if(!(tmpbuf = OPENSSL_malloc(flen)) ) { CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, ERR_R_MALLOC_FAILURE); return -1; } for(i = 0; i < flen; i++) tmpbuf[flen - i - 1] = from[i]; /* Finally decrypt it */ if(!CryptDecrypt(capi_key->key, 0, TRUE, 0, tmpbuf, &flen)) { CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_DECRYPT_ERROR); capi_addlasterror(); OPENSSL_free(tmpbuf); return -1; } else memcpy(to, tmpbuf, flen); OPENSSL_free(tmpbuf); return flen; }
HCERTSTORE capi_open_store(CAPI_CTX * ctx, char *storename) { HCERTSTORE hstore; if (!storename) storename = ctx->storename; if (!storename) storename = "MY"; CAPI_trace(ctx, "Opening certificate store %s\n", storename); hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, ctx->store_flags, storename); if (!hstore) { CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE); capi_addlasterror(); } return hstore; }
static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, int check) { CAPI_trace(ctx, "capi_ctx_set_provname, name=%s, type=%d\n", pname, type); if (check) { HCRYPTPROV hprov; if (!CryptAcquireContextA(&hprov, NULL, pname, type, CRYPT_VERIFYCONTEXT)) { CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); capi_addlasterror(); return 0; } CryptReleaseContext(hprov, 0); } ctx->cspname = BUF_strdup(pname); ctx->csptype = type; return 1; }
char * capi_cert_get_fname(CAPI_CTX *ctx, PCCERT_CONTEXT cert) { LPWSTR wfname; DWORD dlen; CAPI_trace(ctx, "capi_cert_get_fname\n"); if (!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dlen)) return NULL; wfname = OPENSSL_malloc(dlen); if (CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, wfname, &dlen)) { char *fname = wide_to_asc(wfname); OPENSSL_free(wfname); return fname; } CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, CAPI_R_ERROR_GETTING_FRIENDLY_NAME); capi_addlasterror(); OPENSSL_free(wfname); return NULL; }
CRYPT_KEY_PROV_INFO *capi_get_prov_info(CAPI_CTX *ctx, PCCERT_CONTEXT cert) { DWORD len; CRYPT_KEY_PROV_INFO *pinfo; if(!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &len)) return NULL; pinfo = OPENSSL_malloc(len); if (!pinfo) { CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, ERR_R_MALLOC_FAILURE); return NULL; } if(!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len)) { CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO); capi_addlasterror(); OPENSSL_free(pinfo); return NULL; } return pinfo; }
static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen, DSA *dsa) { HCRYPTHASH hash; DWORD slen; DSA_SIG *ret = NULL; CAPI_KEY *capi_key; CAPI_CTX *ctx; unsigned char csigbuf[40]; ctx = ENGINE_get_ex_data(dsa->engine, capi_idx); CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n"); capi_key = DSA_get_ex_data(dsa, dsa_capi_idx); if (!capi_key) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY); return NULL; } if (dlen != 20) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH); return NULL; } /* Create the hash object */ if(!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash)) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT); capi_addlasterror(); return NULL; } /* Set the hash value to the value passed */ if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0)) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE); capi_addlasterror(); goto err; } /* Finally sign it */ slen = sizeof(csigbuf); if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH); capi_addlasterror(); goto err; } else { ret = DSA_SIG_new(); if (!ret) goto err; ret->r = BN_new(); ret->s = BN_new(); if (!ret->r || !ret->s) goto err; if (!lend_tobn(ret->r, csigbuf, 20) || !lend_tobn(ret->s, csigbuf + 20, 20)) { DSA_SIG_free(ret); ret = NULL; goto err; } } /* Now cleanup */ err: OPENSSL_cleanse(csigbuf, 40); CryptDestroyHash(hash); return ret; }
int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, const RSA *rsa) { ALG_ID alg; HCRYPTHASH hash; DWORD slen; unsigned int i; int ret = -1; CAPI_KEY *capi_key; CAPI_CTX *ctx; ctx = ENGINE_get_ex_data(rsa->engine, capi_idx); CAPI_trace(ctx, "Called CAPI_rsa_sign()\n"); capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); if (!capi_key) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY); return -1; } /* Convert the signature type to a CryptoAPI algorithm ID */ switch(dtype) { case NID_sha1: alg = CALG_SHA1; break; case NID_md5: alg = CALG_MD5; break; case NID_md5_sha1: alg = CALG_SSL3_SHAMD5; break; default: { char algstr[10]; BIO_snprintf(algstr, 10, "%lx", dtype); CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID); ERR_add_error_data(2, "NID=0x", algstr); return -1; } } /* Create the hash object */ if(!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT); capi_addlasterror(); return -1; } /* Set the hash value to the value passed */ if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE); capi_addlasterror(); goto err; } /* Finally sign it */ slen = RSA_size(rsa); if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH); capi_addlasterror(); goto err; } else { ret = 1; /* Inplace byte reversal of signature */ for(i = 0; i < slen / 2; i++) { unsigned char c; c = sigret[i]; sigret[i] = sigret[slen - i - 1]; sigret[slen - i - 1] = c; } *siglen = slen; } /* Now cleanup */ err: CryptDestroyHash(hash); return ret; }
static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key) { unsigned char *pubkey = NULL; DWORD len; BLOBHEADER *bh; RSA *rkey = NULL; DSA *dkey = NULL; EVP_PKEY *ret = NULL; if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len)) { CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR); capi_addlasterror(); return NULL; } pubkey = OPENSSL_malloc(len); if (!pubkey) goto memerr; if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len)) { CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR); capi_addlasterror(); goto err; } bh = (BLOBHEADER *)pubkey; if (bh->bType != PUBLICKEYBLOB) { CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB); goto err; } if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX) { RSAPUBKEY *rp; DWORD rsa_modlen; unsigned char *rsa_modulus; rp = (RSAPUBKEY *)(bh + 1); if (rp->magic != 0x31415352) { char magstr[10]; BIO_snprintf(magstr, 10, "%lx", rp->magic); CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); ERR_add_error_data(2, "magic=0x", magstr); goto err; } rsa_modulus = (unsigned char *)(rp + 1); rkey = RSA_new_method(eng); if (!rkey) goto memerr; rkey->e = BN_new(); rkey->n = BN_new(); if (!rkey->e || !rkey->n) goto memerr; if (!BN_set_word(rkey->e, rp->pubexp)) goto memerr; rsa_modlen = rp->bitlen / 8; if (!lend_tobn(rkey->n, rsa_modulus, rsa_modlen)) goto memerr; RSA_set_ex_data(rkey, rsa_capi_idx, key); if (!(ret = EVP_PKEY_new())) goto memerr; EVP_PKEY_assign_RSA(ret, rkey); rkey = NULL; } else if (bh->aiKeyAlg == CALG_DSS_SIGN) { DSSPUBKEY *dp; DWORD dsa_plen; unsigned char *btmp; dp = (DSSPUBKEY *)(bh + 1); if (dp->magic != 0x31535344) { char magstr[10]; BIO_snprintf(magstr, 10, "%lx", dp->magic); CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); ERR_add_error_data(2, "magic=0x", magstr); goto err; } dsa_plen = dp->bitlen / 8; btmp = (unsigned char *)(dp + 1); dkey = DSA_new_method(eng); if (!dkey) goto memerr; dkey->p = BN_new(); dkey->q = BN_new(); dkey->g = BN_new(); dkey->pub_key = BN_new(); if (!dkey->p || !dkey->q || !dkey->g || !dkey->pub_key) goto memerr; if (!lend_tobn(dkey->p, btmp, dsa_plen)) goto memerr; btmp += dsa_plen; if (!lend_tobn(dkey->q, btmp, 20)) goto memerr; btmp += 20; if (!lend_tobn(dkey->g, btmp, dsa_plen)) goto memerr; btmp += dsa_plen; if (!lend_tobn(dkey->pub_key, btmp, dsa_plen)) goto memerr; btmp += dsa_plen; DSA_set_ex_data(dkey, dsa_capi_idx, key); if (!(ret = EVP_PKEY_new())) goto memerr; EVP_PKEY_assign_DSA(ret, dkey); dkey = NULL; } else { char algstr[10]; BIO_snprintf(algstr, 10, "%lx", bh->aiKeyAlg); CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM); ERR_add_error_data(2, "aiKeyAlg=0x", algstr); goto err; } err: if (pubkey) OPENSSL_free(pubkey); if (!ret) { if (rkey) RSA_free(rkey); if (dkey) DSA_free(dkey); } return ret; memerr: CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE); goto err; }
static int capi_list_containers(CAPI_CTX *ctx, BIO *out) { int ret = 1; HCRYPTPROV hprov; DWORD err, idx, flags, buflen = 0, clen; LPSTR cname; CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname, ctx->csptype); if (!CryptAcquireContextA(&hprov, NULL, ctx->cspname, ctx->csptype, CRYPT_VERIFYCONTEXT)) { CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); capi_addlasterror(); return 0; } if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, NULL, &buflen, CRYPT_FIRST)) { CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR); capi_addlasterror(); return 0; } CAPI_trace(ctx, "Got max container len %d\n", buflen); if (buflen == 0) buflen = 1024; cname = OPENSSL_malloc(buflen); if (!cname) { CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE); goto err; } for (idx = 0;;idx++) { clen = buflen; cname[0] = 0; if (idx == 0) flags = CRYPT_FIRST; else flags = 0; if(!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, cname, &clen, flags)) { err = GetLastError(); if (err == ERROR_NO_MORE_ITEMS) goto done; CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR); capi_adderror(err); goto err; } CAPI_trace(ctx, "Container name %s, len=%d, index=%d, flags=%d\n", cname, clen, idx, flags); if (!cname[0] && (clen == buflen)) { CAPI_trace(ctx, "Enumerate bug: using workaround\n"); goto done; } BIO_printf(out, "%d. %s\n", idx, cname); } err: ret = 0; done: if (cname) OPENSSL_free(cname); CryptReleaseContext(hprov, 0); return ret; }