/** * ECDSA signing method (replaces ossl_ecdsa_sign_sig) * * @param dgst hash value to sign * @param dlen length of the hash value * @param kinv precomputed inverse k (from the sign_setup method) * @param rp precomputed rp (from the sign_setup method) * @param ec private EC signing key * @return pointer to a ECDSA_SIG structure or NULL if an error occurred */ static ECDSA_SIG *pkcs11_ecdsa_sign_sig(const unsigned char *dgst, int dlen, const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *ec) { unsigned char sigret[512]; /* HACK for now */ ECDSA_SIG *sig; PKCS11_KEY *key; unsigned int siglen; BIGNUM *r, *s, *order; (void)kinv; /* Precomputed values are not used for PKCS#11 */ (void)rp; /* Precomputed values are not used for PKCS#11 */ key = pkcs11_get_ex_data_ec(ec); if (check_key_fork(key) < 0) { sign_sig_fn orig_sign_sig; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) const EC_KEY_METHOD *meth = EC_KEY_OpenSSL(); EC_KEY_METHOD_get_sign((EC_KEY_METHOD *)meth, NULL, NULL, &orig_sign_sig); #else const ECDSA_METHOD *meth = ECDSA_OpenSSL(); orig_sign_sig = meth->ecdsa_do_sign; #endif return orig_sign_sig(dgst, dlen, kinv, rp, ec); } /* Truncate digest if its byte size is longer than needed */ order = BN_new(); if (order) { const EC_GROUP *group = EC_KEY_get0_group(ec); if (group && EC_GROUP_get_order(group, order, NULL)) { int klen = BN_num_bits(order); if (klen < 8*dlen) dlen = (klen+7)/8; } BN_free(order); } siglen = sizeof sigret; if (pkcs11_ecdsa_sign(dgst, dlen, sigret, &siglen, key) <= 0) return NULL; r = BN_bin2bn(sigret, siglen/2, NULL); s = BN_bin2bn(sigret + siglen/2, siglen/2, NULL); sig = ECDSA_SIG_new(); if (sig == NULL) return NULL; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ECDSA_SIG_set0(sig, r, s); #else BN_free(sig->r); sig->r = r; BN_free(sig->s); sig->s = s; #endif return sig; }
/** * ECDSA signing method (replaces ossl_ecdsa_sign_sig) * * @param dgst hash value to sign * @param dlen length of the hash value * @param kinv precomputed inverse k (from the sign_setup method) * @param rp precomputed rp (from the sign_setup method) * @param ec private EC signing key * @return pointer to a ECDSA_SIG structure or NULL if an error occurred */ static ECDSA_SIG *pkcs11_ecdsa_sign_sig(const unsigned char *dgst, int dlen, const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *ec) { unsigned char sigret[512]; /* HACK for now */ ECDSA_SIG *sig; PKCS11_KEY *key; unsigned int siglen; BIGNUM *r, *s, *order; (void)kinv; /* Precomputed values are not used for PKCS#11 */ (void)rp; /* Precomputed values are not used for PKCS#11 */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L key = (PKCS11_KEY *)EC_KEY_get_ex_data(ec, ec_ex_index); #else key = (PKCS11_KEY *)ECDSA_get_ex_data(ec, ec_ex_index); #endif if (key == NULL) { PKCS11err(PKCS11_F_PKCS11_EC_KEY_SIGN, PKCS11_ALIEN_KEY); return NULL; } /* TODO: Add an atfork check */ /* Truncate digest if its byte size is longer than needed */ order = BN_new(); if (order) { const EC_GROUP *group = EC_KEY_get0_group(ec); if (group && EC_GROUP_get_order(group, order, NULL)) { int klen = BN_num_bits(order); if (klen < 8*dlen) dlen = (klen+7)/8; } BN_free(order); } siglen = sizeof sigret; if (pkcs11_ecdsa_sign(dgst, dlen, sigret, &siglen, key) <= 0) return NULL; sig = ECDSA_SIG_new(); if (sig == NULL) return NULL; #if OPENSSL_VERSION_NUMBER >= 0x10100000L ECDSA_SIG_get0(&r, &s, sig); #else r = sig->r; s = sig->s; #endif BN_bin2bn(sigret, siglen/2, r); BN_bin2bn(sigret + siglen/2, siglen/2, s); return sig; }