int test_builtin(BIO *out) { EC_builtin_curve *curves = NULL; size_t crv_len = 0, n = 0; EC_KEY *eckey = NULL, *wrong_eckey = NULL; EC_GROUP *group; ECDSA_SIG *ecdsa_sig = NULL; unsigned char digest[20], wrong_digest[20]; unsigned char *signature = NULL; const unsigned char *sig_ptr; unsigned char *sig_ptr2; unsigned char *raw_buf = NULL; unsigned int sig_len, degree, r_len, s_len, bn_len, buf_len; int nid, ret = 0; /* fill digest values with some random data */ if (!RAND_pseudo_bytes(digest, 20) || !RAND_pseudo_bytes(wrong_digest, 20)) { BIO_printf(out, "ERROR: unable to get random data\n"); goto builtin_err; } /* * create and verify a ecdsa signature with every availble curve (with ) */ BIO_printf(out, "\ntesting ECDSA_sign() and ECDSA_verify() " "with some internal curves:\n"); /* get a list of all internal curves */ crv_len = EC_get_builtin_curves(NULL, 0); curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len); if (curves == NULL) { BIO_printf(out, "malloc error\n"); goto builtin_err; } if (!EC_get_builtin_curves(curves, crv_len)) { BIO_printf(out, "unable to get internal curves\n"); goto builtin_err; } /* now create and verify a signature for every curve */ for (n = 0; n < crv_len; n++) { unsigned char dirt, offset; nid = curves[n].nid; if (nid == NID_ipsec4) continue; /* create new ecdsa key (== EC_KEY) */ if ((eckey = EC_KEY_new()) == NULL) goto builtin_err; group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) goto builtin_err; if (EC_KEY_set_group(eckey, group) == 0) goto builtin_err; EC_GROUP_free(group); degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey)); if (degree < 160) /* drop the curve */ { EC_KEY_free(eckey); eckey = NULL; continue; } BIO_printf(out, "%s: ", OBJ_nid2sn(nid)); /* create key */ if (!EC_KEY_generate_key(eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } /* create second key */ if ((wrong_eckey = EC_KEY_new()) == NULL) goto builtin_err; group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) goto builtin_err; if (EC_KEY_set_group(wrong_eckey, group) == 0) goto builtin_err; EC_GROUP_free(group); if (!EC_KEY_generate_key(wrong_eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* check key */ if (!EC_KEY_check_key(eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* create signature */ sig_len = ECDSA_size(eckey); if ((signature = OPENSSL_malloc(sig_len)) == NULL) goto builtin_err; if (!ECDSA_sign(0, digest, 20, signature, &sig_len, eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* verify signature */ if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* verify signature with the wrong key */ if (ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* wrong digest */ if (ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* wrong length */ if (ECDSA_verify(0, digest, 20, signature, sig_len - 1, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* * Modify a single byte of the signature: to ensure we don't garble * the ASN1 structure, we read the raw signature and modify a byte in * one of the bignums directly. */ sig_ptr = signature; if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len)) == NULL) { BIO_printf(out, " failed\n"); goto builtin_err; } /* Store the two BIGNUMs in raw_buf. */ r_len = BN_num_bytes(ecdsa_sig->r); s_len = BN_num_bytes(ecdsa_sig->s); bn_len = (degree + 7) / 8; if ((r_len > bn_len) || (s_len > bn_len)) { BIO_printf(out, " failed\n"); goto builtin_err; } buf_len = 2 * bn_len; if ((raw_buf = OPENSSL_malloc(buf_len)) == NULL) goto builtin_err; /* Pad the bignums with leading zeroes. */ memset(raw_buf, 0, buf_len); BN_bn2bin(ecdsa_sig->r, raw_buf + bn_len - r_len); BN_bn2bin(ecdsa_sig->s, raw_buf + buf_len - s_len); /* Modify a single byte in the buffer. */ offset = raw_buf[10] % buf_len; dirt = raw_buf[11] ? raw_buf[11] : 1; raw_buf[offset] ^= dirt; /* Now read the BIGNUMs back in from raw_buf. */ if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) || (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL)) goto builtin_err; sig_ptr2 = signature; sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2); if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } /* * Sanity check: undo the modification and verify signature. */ raw_buf[offset] ^= dirt; if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) || (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL)) goto builtin_err; sig_ptr2 = signature; sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2); if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); BIO_printf(out, " ok\n"); /* cleanup */ /* clean bogus errors */ ERR_clear_error(); OPENSSL_free(signature); signature = NULL; EC_KEY_free(eckey); eckey = NULL; EC_KEY_free(wrong_eckey); wrong_eckey = NULL; ECDSA_SIG_free(ecdsa_sig); ecdsa_sig = NULL; OPENSSL_free(raw_buf); raw_buf = NULL; } ret = 1; builtin_err: if (eckey) EC_KEY_free(eckey); if (wrong_eckey) EC_KEY_free(wrong_eckey); if (ecdsa_sig) ECDSA_SIG_free(ecdsa_sig); if (signature) OPENSSL_free(signature); if (raw_buf) OPENSSL_free(raw_buf); if (curves) OPENSSL_free(curves); return ret; }
bool CKey::ReserealizeSignature(std::vector<unsigned char>& vchSig) { unsigned char *pos; if (vchSig.empty()) return false; pos = &vchSig[0]; ECDSA_SIG *sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&pos, vchSig.size()); if (sig == NULL) return false; bool ret = false; int nSize = i2d_ECDSA_SIG(sig, NULL); if (nSize > 0) { vchSig.resize(nSize); // grow or shrink as needed pos = &vchSig[0]; i2d_ECDSA_SIG(sig, &pos); ret = true; } ECDSA_SIG_free(sig); return ret; }
/* returns * 1: correct signature * 0: incorrect signature * -1: error */ int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sigbuf, int sig_len, EC_KEY *eckey) { ECDSA_SIG *s; unsigned char *der = NULL; const unsigned char *p = sigbuf; int derlen = -1; int ret = -1; s = ECDSA_SIG_new(); if (s == NULL) return (ret); if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) goto err; /* Ensure signature uses DER and doesn't have trailing garbage */ derlen = i2d_ECDSA_SIG(s, &der); if (derlen != sig_len || memcmp(sigbuf, der, derlen)) goto err; ret = ECDSA_do_verify(dgst, dgst_len, s, eckey); err: freezero(der, derlen); ECDSA_SIG_free(s); return (ret); }
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig) { vchSig.clear(); ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); if (sig==NULL) return false; const EC_GROUP *group = EC_KEY_get0_group(pkey); CBigNum order, halforder; EC_GROUP_get_order(group, &order, NULL); BN_rshift1(&halforder, &order); // enforce low S values, by negating the value (modulo the order) if above order/2. if (BN_cmp(sig->s, &halforder) > 0) { BN_sub(sig->s, &order, sig->s); } unsigned int nSize = ECDSA_size(pkey); vchSig.resize(nSize); // Make sure it is big enough unsigned char *pos = &vchSig[0]; nSize = i2d_ECDSA_SIG(sig, &pos); ECDSA_SIG_free(sig); vchSig.resize(nSize); // Shrink to fit actual size // Testing our new signature if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) { vchSig.clear(); return false; } return true; }
/** * Setup the ECDSA signature in its encoding that the library wants. * Converts from plain numbers to ASN formatted. * @param sig: input is signature, output alloced ptr (unless failure). * caller must free alloced ptr if this routine returns true. * @param len: input is initial siglen, output is output len. * @return false on failure. */ static int setup_ecdsa_sig(unsigned char** sig, unsigned int* len) { ECDSA_SIG* ecdsa_sig; int newlen; int bnsize = (int)((*len)/2); /* if too short or not even length, fails */ if(*len < 16 || bnsize*2 != (int)*len) return 0; /* use the raw data to parse two evenly long BIGNUMs, "r | s". */ ecdsa_sig = ECDSA_SIG_new(); if(!ecdsa_sig) return 0; ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r); ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s); if(!ecdsa_sig->r || !ecdsa_sig->s) { ECDSA_SIG_free(ecdsa_sig); return 0; } /* spool it into ASN format */ *sig = NULL; newlen = i2d_ECDSA_SIG(ecdsa_sig, sig); if(newlen <= 0) { ECDSA_SIG_free(ecdsa_sig); free(*sig); return 0; } *len = (unsigned int)newlen; ECDSA_SIG_free(ecdsa_sig); return 1; }
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig) { vchSig.clear(); ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); if (sig == NULL) return false; BN_CTX *ctx = BN_CTX_new(); BN_CTX_start(ctx); const EC_GROUP *group = EC_KEY_get0_group(pkey); BIGNUM *order = BN_CTX_get(ctx); BIGNUM *halforder = BN_CTX_get(ctx); EC_GROUP_get_order(group, order, ctx); BN_rshift1(halforder, order); if (BN_cmp(sig->s, halforder) > 0) { // enforce low S values, by negating the value (modulo the order) if above order/2. BN_sub(sig->s, order, sig->s); } BN_CTX_end(ctx); BN_CTX_free(ctx); unsigned int nSize = ECDSA_size(pkey); vchSig.resize(nSize); // Make sure it is big enough unsigned char *pos = &vchSig[0]; nSize = i2d_ECDSA_SIG(sig, &pos); ECDSA_SIG_free(sig); vchSig.resize(nSize); // Shrink to fit actual size return true; }
int ECDSA_sign_ex(int type, const unsigned char *dgst, int dlen, unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey) { // BIO *out;//Added for test ECDSA_SIG *s; //Added for test // out=BIO_new(BIO_s_file()); // if (out == NULL) return 0; // BIO_set_fp(out,stdout,BIO_NOCLOSE); s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); if (s == NULL) { *siglen=0; return 0; } // printf("--------%s(%d),*siglen=%d-------\n",__FUNCTION__,__LINE__,*siglen);//Added for test // BN_print(out, s->r);//Added for test // BN_print(out, s->s);//Added for test *siglen = i2d_ECDSA_SIG(s, &sig); // printf("\n--------%s(%d),*siglen=%d-------\n",__FUNCTION__,__LINE__,*siglen);//Added for test ECDSA_SIG_free(s); return 1; }
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig) { if (vchSig.empty()) return false; // New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first. unsigned char *norm_der = NULL; ECDSA_SIG *norm_sig = ECDSA_SIG_new(); const unsigned char* sigptr = &vchSig[0]; assert(norm_sig); if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL) { /* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on * error. But OpenSSL's own use of this function redundantly frees the * result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a * clear contract for the function behaving the same way is more * conservative. */ ECDSA_SIG_free(norm_sig); return false; } int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der); ECDSA_SIG_free(norm_sig); if (derlen <= 0) return false; // -1 = error, 0 = bad sig, 1 = good bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1; OPENSSL_free(norm_der); return ret; }
// Credit: https://github.com/ppcoin/ppcoin/pull/101/files bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSigParam) { // Prevent the problem described here: // https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-July/009697.html // by removing the extra length bytes std::vector<unsigned char> vchSig(vchSigParam.begin(), vchSigParam.end()); if (vchSig.size() > 1 && vchSig[1] & 0x80) { unsigned char nLengthBytes = vchSig[1] & 0x7f; if (vchSig.size() < 2 + nLengthBytes) return false; if (nLengthBytes > 4) { unsigned char nExtraBytes = nLengthBytes - 4; for (unsigned char i = 0; i < nExtraBytes; i++) if (vchSig[2 + i]) return false; vchSig.erase(vchSig.begin() + 2, vchSig.begin() + 2 + nExtraBytes); vchSig[1] = 0x80 | (nLengthBytes - nExtraBytes); } } if (vchSig.empty()) return false; // New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first. unsigned char *norm_der = NULL; ECDSA_SIG *norm_sig = ECDSA_SIG_new(); const unsigned char* sigptr = &vchSig[0]; assert(norm_sig); if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL) { /* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on * error. But OpenSSL's own use of this function redundantly frees the * result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a * clear contract for the function behaving the same way is more * conservative. */ ECDSA_SIG_free(norm_sig); return false; } int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der); ECDSA_SIG_free(norm_sig); if (derlen <= 0) return false; // -1 = error, 0 = bad sig, 1 = good bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1; OPENSSL_free(norm_der); return ret; }
int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey) { ECDSA_SIG *s; RAND_seed(dgst, dlen); s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); if (s == NULL) { *siglen = 0; return 0; } *siglen = i2d_ECDSA_SIG(s, &sig); ECDSA_SIG_free(s); return 1; }
/*! * \brief Verify the DNSSEC signature for supplied data and ECDSA algorithm. * \see any_sign_verify */ static int ecdsa_sign_verify(const knot_dnssec_sign_context_t *context, const uint8_t *signature, size_t signature_size) { assert(context); assert(signature); if (signature_size != ecdsa_sign_size(context->key)) { return KNOT_EINVAL; } // see ecdsa_sign_write() for conversion details size_t parameter_size = signature_size / 2; const uint8_t *signature_r = signature; const uint8_t *signature_s = signature + parameter_size; ECDSA_SIG *decoded = ECDSA_SIG_new(); if (!decoded) { return KNOT_ENOMEM; } decoded->r = BN_bin2bn(signature_r, parameter_size, decoded->r); decoded->s = BN_bin2bn(signature_s, parameter_size, decoded->s); size_t max_size = EVP_PKEY_size(context->key->data->private_key); uint8_t *raw_signature = malloc(max_size); if (!raw_signature) { ECDSA_SIG_free(decoded); return KNOT_ENOMEM; } uint8_t *raw_write = raw_signature; int raw_size = i2d_ECDSA_SIG(decoded, &raw_write); if (raw_size < 0) { free(raw_signature); ECDSA_SIG_free(decoded); return KNOT_DNSSEC_EDECODE_RAW_SIGNATURE; } assert(raw_write == raw_signature + raw_size); int result = any_sign_verify(context, raw_signature, raw_size); ECDSA_SIG_free(decoded); free(raw_signature); return result; }
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSigParam) { // Fix invalid signature with crafted length by removing extra length bytes std::vector<unsigned char> vchSig(vchSigParam.begin(), vchSigParam.end()); if (vchSig.size() > 1 && vchSig[1] & 0x80) { unsigned char nLengthBytes = vchSig[1] & 0x7f; if (vchSig.size() < 2 + nLengthBytes) // Avoid invalid memory access on crafted signature return false; if (nLengthBytes > 4) { unsigned char nExtraBytes = nLengthBytes - 4; for (unsigned char i = 0; i < nExtraBytes; i++) if (vchSig[2 + i]) return false; vchSig.erase(vchSig.begin() + 2, vchSig.begin() + 2 + nExtraBytes); vchSig[1] = 0x80 | (nLengthBytes - nExtraBytes); } } if (vchSig.empty()) return false; // New versions of OpenSSL will reject non-canonical DER signatures. De/re-serialize first. unsigned char *norm_der = NULL; ECDSA_SIG *norm_sig = ECDSA_SIG_new(); const unsigned char* sigptr = &vchSig[0]; assert(norm_sig); if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL) { /* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on error. * But OpenSSL's own use of this function redundantly frees the result. * As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a clear contract for the function behaving the same way is more conservative. */ ECDSA_SIG_free(norm_sig); return false; } int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der); ECDSA_SIG_free(norm_sig); if (derlen <= 0) return false; // -1 = error, 0 = bad sig, 1 = good bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1; OPENSSL_free(norm_der); return ret; }
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig) { // New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first. unsigned char *norm_der = NULL; ECDSA_SIG *norm_sig = ECDSA_SIG_new(); const unsigned char* sigptr = &vchSig[0]; d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()); int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der); ECDSA_SIG_free(norm_sig); if (derlen <= 0) return false; // -1 = error, 0 = bad sig, 1 = good bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1; OPENSSL_free(norm_der); return ret; }
BUF_MEM * convert_from_plain_sig(const BUF_MEM *plain_sig) { ECDSA_SIG *ecdsa_sig = NULL; BIGNUM *r, *s; BUF_MEM *x962_sig = NULL; int l; unsigned char *p = NULL; check(plain_sig, "Invalid arguments"); check(plain_sig->length%2 == 0, "Invalid data"); ecdsa_sig = ECDSA_SIG_new(); if (!ecdsa_sig) goto err; /* The first l/2 bytes of the plain signature contain the number r, the second * l/2 bytes contain the number s. */ r = BN_bin2bn((unsigned char *) plain_sig->data, plain_sig->length/2, NULL); s = BN_bin2bn((unsigned char *) plain_sig->data + plain_sig->length/2, plain_sig->length/2, NULL); if (!r || !s || !ECDSA_SIG_set0(ecdsa_sig, r, s)) goto err; r = NULL; s = NULL; /* ASN.1 encode the signature*/ l = i2d_ECDSA_SIG(ecdsa_sig, &p); if (l < 0) goto err; x962_sig = BUF_MEM_create_init(p, l); err: if (p) OPENSSL_free(p); if (ecdsa_sig) ECDSA_SIG_free(ecdsa_sig); if (r) BN_free(r); if (s) BN_free(s); return x962_sig; }
int main(int argc, char **argv) { CK_ULONG nslots; CK_SLOT_ID *pslots = NULL; CK_FUNCTION_LIST *funcs = NULL; CK_UTF8CHAR_PTR opt_pin = NULL; CK_ULONG opt_pin_len = 0; CK_RV rc; CK_ULONG opt_slot = -1; CK_SESSION_HANDLE h_session; char *opt_module = NULL, *opt_dir = NULL; /* struct sockaddr_un sockaddr; */ int long_optind = 0; int fd, verbose = 0; key_id_t *rsa_keys, *ec_keys; CK_ULONG rsa_len = 0, ec_len = 0, i; init_crypto(); while (1) { char c = getopt_long(argc, argv, "d:hp:s:m:v", options, &long_optind); if (c == -1) break; switch (c) { case 'd': opt_dir = optarg; break; case 'p': opt_pin = (CK_UTF8CHAR_PTR) strdup(optarg); if(opt_pin) { opt_pin_len = strlen(optarg); } break; case 's': opt_slot = (CK_SLOT_ID) atoi(optarg); break; case 'm': opt_module = optarg; break; case 'v': verbose = 1; break; case 'h': default: print_usage_and_die(app_name, options, option_help); } } rc = pkcs11_load_init(opt_module, opt_dir, stderr, &funcs); if (rc != CKR_OK) { return rc; } rc = pkcs11_get_slots(funcs, stderr, &pslots, &nslots); if (rc != CKR_OK) { return rc; } if(opt_slot == -1) { if(nslots < 1) { /* No slots */ return -1; } else { opt_slot = pslots[0]; } } else { /* Check selected slot is in pslots */ } fprintf(stderr, "Slot: %ld\n", opt_slot); rc = pkcs11_login_session(funcs, stderr, opt_slot, &h_session, CK_TRUE, CKU_USER, opt_pin, opt_pin_len); if (rc != CKR_OK) { show_error(stderr, "Login", rc); return rc; } load_keys(funcs, h_session, CKK_RSA, &rsa_keys, &rsa_len); load_keys(funcs, h_session, CKK_EC, &ec_keys, &ec_len); /* fd = nw_unix_server("pkcs11d.sock", &sockaddr, 0, 0, 0, 64); */ /* close(fd); */ fd = nw_tcp_server(1234, 0, 64); do { struct sockaddr address; socklen_t a_len = sizeof(address); int s = accept(fd, &address, &a_len); BIO *b = BIO_new_socket(s, BIO_NOCLOSE); BIO *buf = BIO_new(BIO_f_buffer()); b = BIO_push(buf, b); char buffer[4096], sig[4096], keyid[KEY_ID_SIZE + 1]; int l, slen = 0, plen = 0; CK_KEY_TYPE type; CK_ATTRIBUTE_TYPE operation; EVP_PKEY *pkey = NULL; l = BIO_gets(b, buffer, sizeof(buffer)); if(l <= 0) { fprintf(stderr, "Error reading query line\n"); goto end; } if(strncmp(buffer, "POST /sign/rsa/", 15) == 0) { memcpy(keyid, buffer + 15, KEY_ID_SIZE - 1); type = CKK_RSA; operation = CKA_SIGN; } else if(strncmp(buffer, "POST /decrypt/rsa/", 18) == 0) { memcpy(keyid, buffer + 18, KEY_ID_SIZE - 1); type = CKK_RSA; operation = CKA_DECRYPT; } else if(strncmp(buffer, "POST /sign/ec/", 14) == 0) { memcpy(keyid, buffer + 14, KEY_ID_SIZE - 1); type = CKK_EC; operation = CKA_SIGN; } else { goto end; } keyid[KEY_ID_SIZE] = '\0'; l = BIO_gets(b, buffer, sizeof(buffer)); if((l <= 0) || strncmp(buffer, "Content-Length: ", 16) != 0) { fprintf(stderr, "Invalid content length line = %s\n", buffer); goto end; } plen = atoi(buffer + 16); l = BIO_gets(b, buffer, sizeof(buffer)); l = BIO_read(b, buffer, plen); if(l < plen) { fprintf(stderr, "Error reading payload\n"); goto end; } if(type == CKK_RSA) { for(i = 0; (i < rsa_len) && (pkey == NULL); i++) { if(strncmp(rsa_keys[i].id, keyid, KEY_ID_SIZE - 1) == 0) { pkey = rsa_keys[i].key; } } } else if(type == CKK_EC) { for(i = 0; (i < ec_len) && (pkey == NULL); i++) { if(strncmp(ec_keys[i].id, keyid, KEY_ID_SIZE - 1) == 0) { pkey = ec_keys[i].key; } } } if(pkey == NULL) { fprintf(stderr, "Key not found\n"); goto end; } else if(verbose) { fprintf(stderr, "Key '%s'found\n", keyid); } if(type == CKK_RSA && operation == CKA_SIGN) { if(verbose) { fprintf(stderr, "RSA signature operation requested\n"); } l = RSA_private_encrypt(plen, (unsigned char *)buffer, (unsigned char *)sig, EVP_PKEY_get1_RSA(pkey), RSA_PKCS1_PADDING); } else if(type == CKK_RSA && operation == CKA_DECRYPT) { if(verbose) { fprintf(stderr, "RSA decryption operation requested\n"); } l = RSA_private_decrypt(plen, (unsigned char *)buffer, (unsigned char *)sig, EVP_PKEY_get1_RSA(pkey), RSA_PKCS1_PADDING); } else if (type == CKK_EC && operation == CKA_SIGN) { unsigned char *ptr = (unsigned char *)sig; ECDSA_SIG *s = ECDSA_do_sign((unsigned char *)buffer, plen, EVP_PKEY_get1_EC_KEY(pkey)); l = i2d_ECDSA_SIG(s, &ptr); ECDSA_SIG_free(s); } else { if(verbose) { fprintf(stderr, "Invalid operation requested\n"); } goto end; } slen = l; if(l <= 0) { if(verbose) { fprintf(stderr, "Error unsuccessful\n"); } goto end; } else if(verbose) { fprintf(stderr, "Operation successful\n"); } BIO_printf(b, "200 Ok\r\n"); BIO_printf(b, "Content-Length: %d\r\n\r\n", slen); l = BIO_write(b, sig, slen); BIO_flush(b); i= 0; /* for(i = 0; i < rsa_len; i++) { BIO_write(b, rsa_keys[i].id, KEY_ID_SIZE); BIO_write(b, "\n", 1); PEM_write_bio_RSAPrivateKey(b, EVP_PKEY_get1_RSA(rsa_keys[i].key), NULL, NULL, 0, NULL, NULL); } for(i = 0; i < ec_len; i++) { BIO_write(b, ec_keys[i].id, KEY_ID_SIZE); BIO_write(b, "\n", 1); PEM_write_bio_ECPrivateKey(b, EVP_PKEY_get1_EC_KEY(ec_keys[i].key), NULL, NULL, 0, NULL, NULL); } */ end: close(s); BIO_free(b); } while(1); close(fd); if(opt_pin) { funcs->C_CloseAllSessions(opt_slot); free(opt_pin); } rc = funcs->C_Finalize(NULL); if (rc != CKR_OK) { show_error(stderr, "C_Finalize", rc); return rc; } return rc; }
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig) { if( fNewerOpenSSL ) { if (vchSig.empty()) return false; // New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first. unsigned char *norm_der = NULL; ECDSA_SIG *norm_sig = ECDSA_SIG_new(); const unsigned char * sigptr = &vchSig[0]; Yassert(norm_sig); if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL) { /* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on * error. But OpenSSL's own use of this function redundantly frees the * result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a * clear contract for the function behaving the same way is more * conservative. */ ECDSA_SIG_free(norm_sig); return false; } int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der); ECDSA_SIG_free(norm_sig); if (derlen <= 0) return false; // -1 = error, 0 = bad sig, 1 = good bool ret = ( 1 == ECDSA_verify( 0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey ) ); OPENSSL_free(norm_der); if (false == ret) return false; return ret; } else // older version of OpenSSL, so do the old code { if (vchSig.empty()) { printf( "\n\aECDSA signature verify called with nul argument?\n\n" ); } const int nECDSAgood = 1, nECDSAbad = 0, nECDSAerror = -1; int nReturn = ECDSA_verify( 0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey ); switch( nReturn ) { case nECDSAgood: return true; case nECDSAbad: //printf( "\n\aECDSA signature verify FAILED?\n\n" ); //(void)MessageBeep( MB_ICONERROR ); return false; case nECDSAerror: //printf( "\n\aECDSA signature verify ERRORED?\n\n" ); //(void)MessageBeep( MB_ICONERROR ); return false; default: return false; } } }
int signMessageWithPem(char *message, char *pem, char **signature) { unsigned int meslen = strlen(message); unsigned char *messagebytes = calloc(meslen, sizeof(unsigned char)); int derSigLen = 0; int i = 0; memcpy(messagebytes, message, meslen); EC_KEY *key = NULL; BIO *in = NULL; unsigned char *buffer = NULL; char *sha256ofMsg = calloc(SHA256_HEX_STRING, sizeof(char)); unsigned char *outBytesOfsha256ofMsg = calloc(SHA256_STRING, sizeof(unsigned char)); digestOfBytes(messagebytes, &sha256ofMsg, "sha256", meslen); sha256ofMsg[64] = '\0'; createDataWithHexString(sha256ofMsg, &outBytesOfsha256ofMsg); in = BIO_new(BIO_s_mem()); BIO_puts(in, pem); key = PEM_read_bio_ECPrivateKey(in, NULL, NULL, NULL); if(key == NULL) { return ERROR; } while(derSigLen < 70 && i < 10) { i++; ECDSA_SIG *sig = ECDSA_do_sign((const unsigned char*)outBytesOfsha256ofMsg, SHA256_DIGEST_LENGTH, key); int verify = ECDSA_do_verify((const unsigned char*)outBytesOfsha256ofMsg, SHA256_DIGEST_LENGTH, sig, key); if(verify != 1) { return ERROR; } int buflen = ECDSA_size(key); buffer = OPENSSL_malloc(buflen); derSigLen = i2d_ECDSA_SIG(sig, &buffer); } if(i == 10) return ERROR; char *hexData = calloc(derSigLen, sizeof(char)); memcpy(hexData, buffer-derSigLen, derSigLen); char *hexString = calloc(derSigLen*2+1, sizeof(char)); toHexString(hexData, derSigLen, &hexString); hexString[derSigLen * 2] = '\0'; memcpy(*signature, hexString, (derSigLen*2)+ 1); EC_KEY_free(key); BIO_free_all(in); free(messagebytes); free(sha256ofMsg); free(outBytesOfsha256ofMsg); free(hexData); free(hexString); return NOERROR; }
int test_builtin(BIO *out) { size_t n = 0; EC_KEY *eckey = NULL, *wrong_eckey = NULL; EC_GROUP *group; BIGNUM *order = NULL; ECDSA_SIG *ecdsa_sig = NULL; unsigned char digest[20], wrong_digest[20]; unsigned char *signature = NULL; const unsigned char *sig_ptr; unsigned char *sig_ptr2; unsigned char *raw_buf = NULL; unsigned int sig_len, r_len, s_len, bn_len, buf_len; int nid, ret = 0; /* fill digest values with some random data */ if (!RAND_pseudo_bytes(digest, 20) || !RAND_pseudo_bytes(wrong_digest, 20)) { BIO_printf(out, "ERROR: unable to get random data\n"); goto builtin_err; } order = BN_new(); if (order == NULL) { goto builtin_err; } /* create and verify a ecdsa signature with every availble curve * (with ) */ BIO_printf(out, "\ntesting ECDSA_sign() and ECDSA_verify() " "with some internal curves:\n"); static const int kCurveNIDs[] = {NID_secp224r1, NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_undef}; /* now create and verify a signature for every curve */ for (n = 0; kCurveNIDs[n] != NID_undef; n++) { unsigned char dirt, offset; nid = kCurveNIDs[n]; /* create new ecdsa key (== EC_KEY) */ eckey = EC_KEY_new(); if (eckey == NULL) { goto builtin_err; } group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) { goto builtin_err; } if (!EC_KEY_set_group(eckey, group)) { goto builtin_err; } EC_GROUP_free(group); if (!EC_GROUP_get_order(EC_KEY_get0_group(eckey), order, NULL)) { goto builtin_err; } if (BN_num_bits(order) < 160) { /* Too small to test. */ EC_KEY_free(eckey); eckey = NULL; continue; } BIO_printf(out, "%s: ", OBJ_nid2sn(nid)); /* create key */ if (!EC_KEY_generate_key(eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } /* create second key */ wrong_eckey = EC_KEY_new(); if (wrong_eckey == NULL) { goto builtin_err; } group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) { goto builtin_err; } if (EC_KEY_set_group(wrong_eckey, group) == 0) { goto builtin_err; } EC_GROUP_free(group); if (!EC_KEY_generate_key(wrong_eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* check key */ if (!EC_KEY_check_key(eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* create signature */ sig_len = ECDSA_size(eckey); signature = OPENSSL_malloc(sig_len); if (signature == NULL) { goto builtin_err; } if (!ECDSA_sign(0, digest, 20, signature, &sig_len, eckey)) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* verify signature */ if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* verify signature with the wrong key */ if (ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* wrong digest */ if (ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* wrong length */ if (ECDSA_verify(0, digest, 20, signature, sig_len - 1, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); /* Modify a single byte of the signature: to ensure we don't * garble the ASN1 structure, we read the raw signature and * modify a byte in one of the bignums directly. */ sig_ptr = signature; ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len); if (ecdsa_sig == NULL) { BIO_printf(out, " failed\n"); goto builtin_err; } /* Store the two BIGNUMs in raw_buf. */ r_len = BN_num_bytes(ecdsa_sig->r); s_len = BN_num_bytes(ecdsa_sig->s); bn_len = BN_num_bytes(order); if (r_len > bn_len || s_len > bn_len) { BIO_printf(out, " failed\n"); goto builtin_err; } buf_len = 2 * bn_len; raw_buf = OPENSSL_malloc(2 * bn_len); if (raw_buf == NULL) { goto builtin_err; } /* Pad the bignums with leading zeroes. */ if (!BN_bn2bin_padded(raw_buf, bn_len, ecdsa_sig->r) || !BN_bn2bin_padded(raw_buf + bn_len, bn_len, ecdsa_sig->s)) { goto builtin_err; } /* Modify a single byte in the buffer. */ offset = raw_buf[10] % buf_len; dirt = raw_buf[11] ? raw_buf[11] : 1; raw_buf[offset] ^= dirt; /* Now read the BIGNUMs back in from raw_buf. */ if (BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL || BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL) { goto builtin_err; } sig_ptr2 = signature; sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2); if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } /* Sanity check: undo the modification and verify signature. */ raw_buf[offset] ^= dirt; if (BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL || BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL) { goto builtin_err; } sig_ptr2 = signature; sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2); if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) { BIO_printf(out, " failed\n"); goto builtin_err; } BIO_printf(out, "."); (void)BIO_flush(out); BIO_printf(out, " ok\n"); /* cleanup */ /* clean bogus errors */ ERR_clear_error(); OPENSSL_free(signature); signature = NULL; EC_KEY_free(eckey); eckey = NULL; EC_KEY_free(wrong_eckey); wrong_eckey = NULL; ECDSA_SIG_free(ecdsa_sig); ecdsa_sig = NULL; OPENSSL_free(raw_buf); raw_buf = NULL; } ret = 1; builtin_err: if (eckey) { EC_KEY_free(eckey); } if (order) { BN_free(order); } if (wrong_eckey) { EC_KEY_free(wrong_eckey); } if (ecdsa_sig) { ECDSA_SIG_free(ecdsa_sig); } if (signature) { OPENSSL_free(signature); } if (raw_buf) { OPENSSL_free(raw_buf); } return ret; }
static int test_builtin(void) { EC_builtin_curve *curves = NULL; size_t crv_len = 0, n = 0; EC_KEY *eckey = NULL, *wrong_eckey = NULL; EC_GROUP *group; ECDSA_SIG *ecdsa_sig = NULL, *modified_sig = NULL; unsigned char digest[20], wrong_digest[20]; unsigned char *signature = NULL; const unsigned char *sig_ptr; unsigned char *sig_ptr2; unsigned char *raw_buf = NULL; const BIGNUM *sig_r, *sig_s; BIGNUM *modified_r = NULL, *modified_s = NULL; BIGNUM *unmodified_r = NULL, *unmodified_s = NULL; unsigned int sig_len, degree, r_len, s_len, bn_len, buf_len; int nid, ret = 0; /* fill digest values with some random data */ if (!TEST_true(RAND_bytes(digest, 20)) || !TEST_true(RAND_bytes(wrong_digest, 20))) goto builtin_err; /* create and verify a ecdsa signature with every available curve */ /* get a list of all internal curves */ crv_len = EC_get_builtin_curves(NULL, 0); if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len)) || !TEST_true(EC_get_builtin_curves(curves, crv_len))) goto builtin_err; /* now create and verify a signature for every curve */ for (n = 0; n < crv_len; n++) { unsigned char dirt, offset; nid = curves[n].nid; if (nid == NID_ipsec4 || nid == NID_X25519) continue; /* create new ecdsa key (== EC_KEY) */ if (!TEST_ptr(eckey = EC_KEY_new()) || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)) || !TEST_true(EC_KEY_set_group(eckey, group))) goto builtin_err; EC_GROUP_free(group); degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey)); if (degree < 160) { /* drop the curve */ EC_KEY_free(eckey); eckey = NULL; continue; } TEST_info("testing %s", OBJ_nid2sn(nid)); /* create key */ if (!TEST_true(EC_KEY_generate_key(eckey))) goto builtin_err; /* create second key */ if (!TEST_ptr(wrong_eckey = EC_KEY_new()) || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)) || !TEST_true(EC_KEY_set_group(wrong_eckey, group))) goto builtin_err; EC_GROUP_free(group); if (!TEST_true(EC_KEY_generate_key(wrong_eckey))) goto builtin_err; /* check key */ if (!TEST_true(EC_KEY_check_key(eckey))) goto builtin_err; /* create signature */ sig_len = ECDSA_size(eckey); if (!TEST_ptr(signature = OPENSSL_malloc(sig_len)) || !TEST_true(ECDSA_sign(0, digest, 20, signature, &sig_len, eckey))) goto builtin_err; /* verify signature */ if (!TEST_int_eq(ECDSA_verify(0, digest, 20, signature, sig_len, eckey), 1)) goto builtin_err; /* verify signature with the wrong key */ if (!TEST_int_ne(ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey), 1)) goto builtin_err; /* wrong digest */ if (!TEST_int_ne(ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey), 1)) goto builtin_err; /* wrong length */ if (!TEST_int_ne(ECDSA_verify(0, digest, 20, signature, sig_len - 1, eckey), 1)) goto builtin_err; /* * Modify a single byte of the signature: to ensure we don't garble * the ASN1 structure, we read the raw signature and modify a byte in * one of the bignums directly. */ sig_ptr = signature; if (!TEST_ptr(ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len))) goto builtin_err; ECDSA_SIG_get0(ecdsa_sig, &sig_r, &sig_s); /* Store the two BIGNUMs in raw_buf. */ r_len = BN_num_bytes(sig_r); s_len = BN_num_bytes(sig_s); bn_len = (degree + 7) / 8; if (!TEST_false(r_len > bn_len) || !TEST_false(s_len > bn_len)) goto builtin_err; buf_len = 2 * bn_len; if (!TEST_ptr(raw_buf = OPENSSL_zalloc(buf_len))) goto builtin_err; BN_bn2bin(sig_r, raw_buf + bn_len - r_len); BN_bn2bin(sig_s, raw_buf + buf_len - s_len); /* Modify a single byte in the buffer. */ offset = raw_buf[10] % buf_len; dirt = raw_buf[11] ? raw_buf[11] : 1; raw_buf[offset] ^= dirt; /* Now read the BIGNUMs back in from raw_buf. */ if (!TEST_ptr(modified_sig = ECDSA_SIG_new())) goto builtin_err; if (!TEST_ptr(modified_r = BN_bin2bn(raw_buf, bn_len, NULL)) || !TEST_ptr(modified_s = BN_bin2bn(raw_buf + bn_len, bn_len, NULL)) || !TEST_true(ECDSA_SIG_set0(modified_sig, modified_r, modified_s))) { BN_free(modified_r); BN_free(modified_s); goto builtin_err; } sig_ptr2 = signature; sig_len = i2d_ECDSA_SIG(modified_sig, &sig_ptr2); if (!TEST_false(ECDSA_verify(0, digest, 20, signature, sig_len, eckey))) goto builtin_err; /* Sanity check: undo the modification and verify signature. */ raw_buf[offset] ^= dirt; if (!TEST_ptr(unmodified_r = BN_bin2bn(raw_buf, bn_len, NULL)) || !TEST_ptr(unmodified_s = BN_bin2bn(raw_buf + bn_len, bn_len, NULL)) || !TEST_true(ECDSA_SIG_set0(modified_sig, unmodified_r, unmodified_s))) { BN_free(unmodified_r); BN_free(unmodified_s); goto builtin_err; } sig_ptr2 = signature; sig_len = i2d_ECDSA_SIG(modified_sig, &sig_ptr2); if (!TEST_true(ECDSA_verify(0, digest, 20, signature, sig_len, eckey))) goto builtin_err; /* cleanup */ ERR_clear_error(); OPENSSL_free(signature); signature = NULL; EC_KEY_free(eckey); eckey = NULL; EC_KEY_free(wrong_eckey); wrong_eckey = NULL; ECDSA_SIG_free(ecdsa_sig); ecdsa_sig = NULL; ECDSA_SIG_free(modified_sig); modified_sig = NULL; OPENSSL_free(raw_buf); raw_buf = NULL; } ret = 1; builtin_err: EC_KEY_free(eckey); EC_KEY_free(wrong_eckey); ECDSA_SIG_free(ecdsa_sig); ECDSA_SIG_free(modified_sig); OPENSSL_free(signature); OPENSSL_free(raw_buf); OPENSSL_free(curves); return ret; }
bool bdoc::X509Cert::verifySignature(int digestMethod, int digestSize, std::vector<unsigned char> digest, std::vector<unsigned char> signature) { int result = 0; EVP_PKEY* key = getPublicKey(); switch (EVP_PKEY_type(key->type)) { case EVP_PKEY_RSA: { if (digest.size() > static_cast<size_t>(digestSize)) { // The digest already has an ASN.1 DigestInfo header. break; } X509_SIG *sig = X509_SIG_new(); // Prefer set0 to set_md, so we don't have to initialize the // digest lookup table with OpenSSL_add_all_digests. None of // our supported digests have parameters anyway. X509_ALGOR_set0(sig->algor, OBJ_nid2obj(digestMethod), V_ASN1_NULL, NULL); ASN1_OCTET_STRING_set(sig->digest, &digest[0], digest.size()); unsigned char *asn1 = NULL; size_t asn1_len = i2d_X509_SIG(sig, &asn1); digest = std::vector<unsigned char>(asn1, asn1 + asn1_len); X509_SIG_free(sig); break; } case EVP_PKEY_EC: { ECDSA_SIG *sig = ECDSA_SIG_new(); // signature is just r and s concatenated, so split them. size_t n_len = signature.size() >> 1; BN_bin2bn(&signature[0], n_len, sig->r); BN_bin2bn(&signature[n_len], n_len, sig->s); unsigned char *asn1 = NULL; size_t asn1_len = i2d_ECDSA_SIG(sig, &asn1); signature = std::vector<unsigned char>(asn1, asn1 + asn1_len); ECDSA_SIG_free(sig); break; } default: THROW_STACK_EXCEPTION("Certificate '%s' has an unsupported " "public key type, can not verify signature.", getSubject().c_str()); } EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL); if (!ctx) { EVP_PKEY_free(key); THROW_STACK_EXCEPTION("Creating signature verification " "context failed: %s", ERR_reason_error_string(ERR_get_error())); } if (EVP_PKEY_verify_init(ctx) <= 0) { EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); THROW_STACK_EXCEPTION("Initializing signature " "verification context failed: %s", ERR_reason_error_string(ERR_get_error())); } result = EVP_PKEY_verify(ctx, &signature[0], signature.size(), &digest[0], digest.size()); if (result < 0) { EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); THROW_STACK_EXCEPTION("Error during signature verification: %s", ERR_reason_error_string(ERR_get_error())); } EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); return (result == 1); }
/** * * \brief Generates a digest then sends the digest to the * ATECCX08 chip to generate an ECDSA signature using * private key from TLS_SLOT_AUTH_PRIV slot. The private * key is always stays in the chip: OpenSSL (nor any * other software) has no way to read it. * * \param[in] ctx - a pointer to the EVP_MD_CTX structure * \param[in] it - a pointer to the ASN1_ITEM structure * \param[in] asn - a void pointer to the parameter * \param[in] algor1 - a pointer to the X509_ALGOR structure * \param[in] algor2 - a pointer to the X509_ALGOR structure * \param[out] signature - a pointer to the ASN1_BIT_STRING * structure to return the signature in the ASN.1 format * \return 1 for success */ int eccx08_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *signature) { int rc = 0; int ret = 0; const EVP_MD *type; EVP_PKEY *pkey; uint8_t *buf_in = NULL, *buf_out = NULL; uint8_t *sig_in = NULL, *sig_out = NULL; size_t inl = 0, outl = 0, outll = 0; int signid, paramtype; uint8_t slotid = TLS_SLOT_AUTH_PRIV; ATCA_STATUS status = ATCA_GEN_FAIL; extern ECDSA_METHOD eccx08_ecdsa; type = EVP_MD_CTX_md(ctx); pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); if (!type || !pkey) { ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED); return 0; } if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { if (!pkey->ameth || !OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(type), pkey->ameth->pkey_id)) { ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); return 0; } } else signid = type->pkey_type; if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) paramtype = V_ASN1_NULL; else paramtype = V_ASN1_UNDEF; if (algor1) X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL); if (algor2) X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL); inl = ASN1_item_i2d(asn, &buf_in, it); outll = outl = EVP_PKEY_size(pkey); buf_out = OPENSSL_malloc((unsigned int)outl); if ((buf_in == NULL) || (buf_out == NULL)) { outl = 0; ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE); goto done; } #ifdef USE_ECCX08 eccx08_debug("eccx08_item_sign() - HW\n"); ret = EVP_DigestUpdate(ctx, buf_in, inl); if (!ret) goto done; ret = EVP_DigestFinal(ctx, buf_out, (unsigned int *)&outl); if (!ret) goto done; sig_in = OPENSSL_malloc((unsigned int)outll); // source of crash sig_out = sig_in; if (sig_in == NULL) { outl = 0; ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE); goto done; } ECDSA_SIG *ecdsasig; ecdsasig = eccx08_ecdsa.ecdsa_do_sign(buf_out, outl, NULL, NULL, pkey->pkey.ec); if (ecdsasig == NULL) goto done; outl = i2d_ECDSA_SIG(ecdsasig, &sig_in); if (ecdsasig->r) { BN_free(ecdsasig->r); ecdsasig->r = NULL; } if (ecdsasig->s) { BN_free(ecdsasig->s); ecdsasig->s = NULL; } ECDSA_SIG_free(ecdsasig); #else // USE_ECCX08 eccx08_debug("eccx08_item_sign() - SW\n"); if (!EVP_DigestSignUpdate(ctx, buf_in, inl) || !EVP_DigestSignFinal(ctx, buf_out, &outl)) { outl = 0; ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB); goto done; } #endif // USE_ECCX08 if (signature->data != NULL) { OPENSSL_free(signature->data); } #ifdef USE_ECCX08 signature->data = sig_out; sig_out = NULL; #else signature->data = buf_out; buf_out = NULL; #endif signature->length = outl; /* * ASN1_item_sign_ctx() in a_sign.c comment (just copy it here): * In the interests of compatibility, I'll make sure that the bit string * has a 'not-used bits' value of 0 */ signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; rc = 1; done: EVP_MD_CTX_cleanup(ctx); if (buf_in != NULL) { OPENSSL_cleanse((char *)buf_in, (unsigned int)inl); OPENSSL_free(buf_in); } if (buf_out != NULL) { OPENSSL_cleanse((char *)buf_out, outll); OPENSSL_free(buf_out); } if (sig_out != NULL) { OPENSSL_cleanse((char *)sig_out, outll); OPENSSL_free(sig_out); } return (rc); }
int jwt_verify_sha_pem(jwt_t *jwt, const char *head, const char *sig_b64) { unsigned char *sig = NULL; EVP_MD_CTX *mdctx = NULL; ECDSA_SIG *ec_sig = NULL; BIGNUM *ec_sig_r = NULL; BIGNUM *ec_sig_s = NULL; EVP_PKEY *pkey = NULL; const EVP_MD *alg; int type; int pkey_type; BIO *bufkey = NULL; int ret = 0; int slen; switch (jwt->alg) { /* RSA */ case JWT_ALG_RS256: alg = EVP_sha256(); type = EVP_PKEY_RSA; break; case JWT_ALG_RS384: alg = EVP_sha384(); type = EVP_PKEY_RSA; break; case JWT_ALG_RS512: alg = EVP_sha512(); type = EVP_PKEY_RSA; break; /* ECC */ case JWT_ALG_ES256: alg = EVP_sha256(); type = EVP_PKEY_EC; break; case JWT_ALG_ES384: alg = EVP_sha384(); type = EVP_PKEY_EC; break; case JWT_ALG_ES512: alg = EVP_sha512(); type = EVP_PKEY_EC; break; default: return EINVAL; } sig = jwt_b64_decode(sig_b64, &slen); if (sig == NULL) VERIFY_ERROR(EINVAL); bufkey = BIO_new_mem_buf(jwt->key, jwt->key_len); if (bufkey == NULL) VERIFY_ERROR(ENOMEM); /* This uses OpenSSL's default passphrase callback if needed. The * library caller can override this in many ways, all of which are * outside of the scope of LibJWT and this is documented in jwt.h. */ pkey = PEM_read_bio_PUBKEY(bufkey, NULL, NULL, NULL); if (pkey == NULL) VERIFY_ERROR(EINVAL); pkey_type = EVP_PKEY_id(pkey); if (pkey_type != type) VERIFY_ERROR(EINVAL); /* Convert EC sigs back to ASN1. */ if (pkey_type == EVP_PKEY_EC) { unsigned int degree, bn_len; unsigned char *p; EC_KEY *ec_key; ec_sig = ECDSA_SIG_new(); if (ec_sig == NULL) VERIFY_ERROR(ENOMEM); /* Get the actual ec_key */ ec_key = EVP_PKEY_get1_EC_KEY(pkey); if (ec_key == NULL) VERIFY_ERROR(ENOMEM); degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec_key)); EC_KEY_free(ec_key); bn_len = (degree + 7) / 8; if ((bn_len * 2) != slen) VERIFY_ERROR(EINVAL); ec_sig_r = BN_bin2bn(sig, bn_len, NULL); ec_sig_s = BN_bin2bn(sig + bn_len, bn_len, NULL); if (ec_sig_r == NULL || ec_sig_s == NULL) VERIFY_ERROR(EINVAL); ECDSA_SIG_set0(ec_sig, ec_sig_r, ec_sig_s); free(sig); slen = i2d_ECDSA_SIG(ec_sig, NULL); sig = malloc(slen); if (sig == NULL) VERIFY_ERROR(ENOMEM); p = sig; slen = i2d_ECDSA_SIG(ec_sig, &p); if (slen == 0) VERIFY_ERROR(EINVAL); } mdctx = EVP_MD_CTX_create(); if (mdctx == NULL) VERIFY_ERROR(ENOMEM); /* Initialize the DigestVerify operation using alg */ if (EVP_DigestVerifyInit(mdctx, NULL, alg, NULL, pkey) != 1) VERIFY_ERROR(EINVAL); /* Call update with the message */ if (EVP_DigestVerifyUpdate(mdctx, head, strlen(head)) != 1) VERIFY_ERROR(EINVAL); /* Now check the sig for validity. */ if (EVP_DigestVerifyFinal(mdctx, sig, slen) != 1) VERIFY_ERROR(EINVAL); jwt_verify_sha_pem_done: if (bufkey) BIO_free(bufkey); if (pkey) EVP_PKEY_free(pkey); if (mdctx) EVP_MD_CTX_destroy(mdctx); if (sig) free(sig); if (ec_sig) ECDSA_SIG_free(ec_sig); return ret; }