int convert_eckey_to_x962_and_print(const EC_KEY* eckey, int version) { assert(eckey); // We don't need to manage the memory for group/point since we're using get0. const EC_GROUP* group = EC_KEY_get0_group(eckey); if (!group) { fprintf(stderr, "error: EC_KEY_get0_group() failed.\n"); return 3; } const EC_POINT* pubkey_point = EC_KEY_get0_public_key(eckey); if (!pubkey_point) { fprintf(stderr, "error: EC_KEY_get0_public_key() failed.\n"); return 3; } size_t octets_len = 256; unsigned char octets[256]; octets_len = EC_POINT_point2oct(group, pubkey_point, POINT_CONVERSION_UNCOMPRESSED, octets, octets_len, NULL); if (0 == octets_len) { fprintf(stderr, "error: EC_POINT_point2oct() failed.\n"); return 3; } if (octets_len != X962_UNCOMPRESSED_SIZE) { fprintf(stderr, "error: EC_POINT_point2oct() produced %lu bytes.\n", (unsigned long) octets_len); return 3; } if (octets[0] != X962_UNCOMPRESSED_HEADER) { fprintf(stderr, "error: EC_POINT_point2oct() produced compressed data.\n"); return 3; } int result = verify_x962_octets_are_on_p256(octets, octets_len); if (result != 0) { return result; } return print_octets(octets, octets_len, version); }
static int pkcs11_ecdh_compute_key_common(unsigned char **out, size_t *outlen, const EC_POINT *point, const EC_KEY *key, struct pkcs11_key_data *pkd) { int rv = 0; if(pkd != NULL) { unsigned char oct[256]; const EC_GROUP *group = EC_KEY_get0_group(key); size_t len = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, oct, sizeof(oct), NULL); if(len > 0) { CK_ECDH1_DERIVE_PARAMS params = { CKD_NULL, 0, NULL, len, oct }; CK_BBOOL ck_true = TRUE; CK_BBOOL ck_false = FALSE; CK_OBJECT_HANDLE derived = CK_INVALID_HANDLE; CK_OBJECT_CLASS class = CKO_SECRET_KEY; CK_KEY_TYPE type = CKK_GENERIC_SECRET; CK_ATTRIBUTE template[] = {
size_t polypseud_decrypt(const polypseud_ctx *ctx, pseudonym *ep, const BIGNUM *privkey, const BIGNUM *closingkey, unsigned char **pp) { if(EC_POINT_mul(ctx->ec_group, ep->a, NULL, ep->a, privkey, ctx->bn_ctx) == 0) return 0; if(EC_POINT_invert(ctx->ec_group, ep->a, ctx->bn_ctx) == 0) return 0; if(EC_POINT_add(ctx->ec_group, ep->a, ep->b, ep->a, ctx->bn_ctx) == 0) return 0; if(EC_POINT_mul(ctx->ec_group, ep->a, NULL, ep->a, closingkey, ctx->bn_ctx) == 0) return 0; unsigned char octstring[100]; size_t len = EC_POINT_point2oct(ctx->ec_group, ep->a, POINT_CONVERSION_UNCOMPRESSED, octstring, 100, ctx->bn_ctx); return hash(octstring, len, pp); }
void b58encode_address(const EC_POINT *ppoint, const EC_GROUP *pgroup, int addrtype, char *result) { unsigned char eckey_buf[128], *pend; unsigned char binres[21] = {0,}; unsigned char hash1[32]; pend = eckey_buf; EC_POINT_point2oct(pgroup, ppoint, POINT_CONVERSION_UNCOMPRESSED, eckey_buf, sizeof(eckey_buf), NULL); pend = eckey_buf + 0x41; binres[0] = addrtype; SHA256(eckey_buf, pend - eckey_buf, hash1); RIPEMD160(hash1, sizeof(hash1), &binres[1]); b58encode_check(binres, sizeof(binres), result); }
void CBAddPoints(uint8_t * point1, uint8_t * point2){ // Get group EC_GROUP * group = EC_GROUP_new_by_curve_name(NID_secp256k1); // Get OpenSSL representations of points EC_POINT * p1 = EC_POINT_new(group); EC_POINT * p2 = EC_POINT_new(group); BN_CTX * ctx = BN_CTX_new(); EC_POINT_oct2point(group, p1, point1, 33, ctx); EC_POINT_oct2point(group, p2, point2, 33, ctx); // Add points together EC_POINT * result = EC_POINT_new(group); EC_POINT_add(group, result, p1, p2, ctx); // Free points EC_POINT_free(p1); EC_POINT_free(p2); // Write result to point1 EC_POINT_point2oct(group, result, POINT_CONVERSION_COMPRESSED, point1, 33, ctx); // Free result, group and ctx EC_POINT_free(result); EC_GROUP_free(group); BN_CTX_free(ctx); }
u2fs_rc dump_user_key(const u2fs_EC_KEY_t * key, char **output) { //TODO add PEM - current output is openssl octet string if (key == NULL || output == NULL) return U2FS_MEMORY_ERROR; EC_GROUP *ecg = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); point_conversion_form_t pcf = POINT_CONVERSION_UNCOMPRESSED; if (ecg == NULL) return U2FS_MEMORY_ERROR; const EC_POINT *point = EC_KEY_get0_public_key((EC_KEY *) key); *output = malloc(U2FS_PUBLIC_KEY_LEN); if (*output == NULL) { EC_GROUP_free(ecg); ecg = NULL; return U2FS_MEMORY_ERROR; } if (EC_POINT_point2oct (ecg, point, pcf, (unsigned char *) *output, U2FS_PUBLIC_KEY_LEN, NULL) != U2FS_PUBLIC_KEY_LEN) { free(ecg); ecg = NULL; free(*output); *output = NULL; return U2FS_CRYPTO_ERROR; } EC_GROUP_free(ecg); ecg = NULL; return U2FS_OK; }
int main() { srand((unsigned)time(NULL)); int i; EC_KEY* key; //key = EC_KEY_new_by_curve_name(415); key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); const EC_GROUP *group = EC_KEY_get0_group(key); if (EC_KEY_generate_key(key)==0) { printf("Error generate key\n"); return -1; } unsigned char pk_b[33]; const EC_POINT *pub = EC_KEY_get0_public_key(key); if (EC_POINT_point2oct(group, pub, POINT_CONVERSION_COMPRESSED, pk_b, 33, 0)!=33) { printf("Error 2\n"); return -1; } unsigned char h1[16],h2[16]; printf("\x02"); for (i=0;i<16;i++) { h1[i]=rand()%256; printf("%c",h1[i]); } for (i=0;i<33;i++) printf("%c",pk_b[i]); fflush(stdout); //get h2 for (i=0;i<16;i++) h2[i]=rand()%256; for (i=0;i<16;i++) scanf("%c",&h2[i]); //get peerpk_b unsigned char peerpk_b[33]={2 , 30 , 25 , 50 , 17 , 242 , 232 , 55 , 157 , 18 , 106 , 115 , 214 , 193 , 192 , 39 , 207 , 226 , 184 , 216 , 244 , 147 , 111 , 188 , 125 , 230 , 38 , 125 , 231 , 50 , 56 , 152 , 148 }; for (i=0;i<33;i++) scanf("%c",&peerpk_b[i]); EC_POINT *peerpk = EC_POINT_new(group); if (EC_POINT_oct2point(group, peerpk, peerpk_b, 33, 0)==0) { printf("Error 3\n"); return -1; } unsigned char skey[33]; if (ECDH_compute_key(skey, 32, peerpk, key, NULL)==0) { printf("Error 4\n"); return -1; } SHA512_CTX shactx; unsigned char hash[SHA512_DIGEST_LENGTH]; SHA512_Init(&shactx); SHA512_Update(&shactx, h2, 16); SHA512_Update(&shactx, skey, 32); SHA512_Update(&shactx, h1, 16); SHA512_Final(hash, &shactx); for (i=0;i<64;i++) printf("%02x",hash[i]); fflush(stdout); struct cipher c; c.recvfd=0; c.sendfd=1; for (i=0;i<16;i++) c.sendkey[i]=hash[i]; for (i=0;i<4;i++) c.sendiv[i]=hash[32+i]; for (i=0;i<16;i++) c.recvkey[i]=hash[16+i]; for (i=0;i<4;i++) c.recviv[i]=hash[36+i]; c.sendcnt=0; c.recvcnt=0; unsigned char d[1000]; unsigned char oiv[8]; int op; char dlen; while (true) { scanf("%d",&op); scanf("%c",&dlen); scanf("%c",&dlen); for (i=0;i<dlen;i++) scanf("%c",&d[i]); if (op==1) { for (i=0;i<8;i++) oiv[i]=rand()%256; encrypt(c,d,dlen,oiv); c.recvcnt+=1; } else if (op==2) { for (i=0;i<8;i++) scanf("%c",&oiv[i]); decrypt(c,d,dlen,oiv, NULL); c.sendcnt+=1; } fflush(stdout); } return 0; }
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){ /* ECDH keys */ ssh_string q_c_string = NULL; ssh_string q_s_string = NULL; EC_KEY *ecdh_key=NULL; const EC_GROUP *group; const EC_POINT *ecdh_pubkey; bignum_CTX ctx; /* SSH host keys (rsa,dsa,ecdsa) */ ssh_key privkey; ssh_string sig_blob = NULL; int len; int rc; enter_function(); /* Extract the client pubkey from the init packet */ q_c_string = buffer_get_ssh_string(packet); if (q_c_string == NULL) { ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet"); goto error; } session->next_crypto->ecdh_client_pubkey = q_c_string; /* Build server's keypair */ ctx = BN_CTX_new(); ecdh_key = EC_KEY_new_by_curve_name(NISTP256); group = EC_KEY_get0_group(ecdh_key); EC_KEY_generate_key(ecdh_key); ecdh_pubkey=EC_KEY_get0_public_key(ecdh_key); len = EC_POINT_point2oct(group,ecdh_pubkey,POINT_CONVERSION_UNCOMPRESSED, NULL,0,ctx); q_s_string=ssh_string_new(len); EC_POINT_point2oct(group,ecdh_pubkey,POINT_CONVERSION_UNCOMPRESSED, ssh_string_data(q_s_string),len,ctx); BN_CTX_free(ctx); session->next_crypto->ecdh_privkey = ecdh_key; session->next_crypto->ecdh_server_pubkey = q_s_string; buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY); /* build k and session_id */ if (ecdh_build_k(session) < 0) { ssh_set_error(session, SSH_FATAL, "Cannot build k number"); goto error; } if (ssh_get_key_params(session, &privkey) == SSH_ERROR) goto error; if (make_sessionid(session) != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not create a session id"); goto error; } /* add host's public key */ buffer_add_ssh_string(session->out_buffer, session->next_crypto->server_pubkey); /* add ecdh public key */ buffer_add_ssh_string(session->out_buffer,q_s_string); /* add signature blob */ sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey); if (sig_blob == NULL) { ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); goto error; } buffer_add_ssh_string(session->out_buffer, sig_blob); ssh_string_free(sig_blob); /* Free private keys as they should not be readable after this point */ if (session->srv.rsa_key) { ssh_key_free(session->srv.rsa_key); session->srv.rsa_key = NULL; } if (session->srv.dsa_key) { ssh_key_free(session->srv.dsa_key); session->srv.dsa_key = NULL; } ssh_log(session,SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent"); rc = packet_send(session); if (rc == SSH_ERROR) goto error; /* Send the MSG_NEWKEYS */ if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { goto error; } session->dh_handshake_state=DH_STATE_NEWKEYS_SENT; rc=packet_send(session); ssh_log(session, SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); return rc; error: return SSH_ERROR; }
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) { uint8_t *buffer = NULL; const char *ecstr; size_t buf_len = 0, i; int ret = 0, reason = ERR_R_BIO_LIB; BN_CTX *ctx = NULL; const EC_GROUP *group; const EC_POINT *public_key; const BIGNUM *priv_key; uint8_t *pub_key_bytes = NULL; size_t pub_key_bytes_len = 0; if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { reason = ERR_R_PASSED_NULL_PARAMETER; goto err; } ctx = BN_CTX_new(); if (ctx == NULL) { reason = ERR_R_MALLOC_FAILURE; goto err; } if (ktype > 0) { public_key = EC_KEY_get0_public_key(x); if (public_key != NULL) { pub_key_bytes_len = EC_POINT_point2oct( group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx); if (pub_key_bytes_len == 0) { reason = ERR_R_MALLOC_FAILURE; goto err; } pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len); if (pub_key_bytes == NULL) { reason = ERR_R_MALLOC_FAILURE; goto err; } pub_key_bytes_len = EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x), pub_key_bytes, pub_key_bytes_len, ctx); if (pub_key_bytes_len == 0) { reason = ERR_R_MALLOC_FAILURE; goto err; } buf_len = pub_key_bytes_len; } } if (ktype == 2) { priv_key = EC_KEY_get0_private_key(x); if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) { buf_len = i; } } else { priv_key = NULL; } if (ktype > 0) { buf_len += 10; if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { reason = ERR_R_MALLOC_FAILURE; goto err; } } if (ktype == 2) { ecstr = "Private-Key"; } else if (ktype == 1) { ecstr = "Public-Key"; } else { ecstr = "ECDSA-Parameters"; } if (!BIO_indent(bp, off, 128)) { goto err; } const BIGNUM *order = EC_GROUP_get0_order(group); if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) { goto err; } if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, buffer, off)) { goto err; } if (pub_key_bytes != NULL) { BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off); } /* TODO(fork): implement */ /* if (!ECPKParameters_print(bp, group, off)) goto err; */ ret = 1; err: if (!ret) { OPENSSL_PUT_ERROR(EVP, reason); } OPENSSL_free(pub_key_bytes); BN_CTX_free(ctx); OPENSSL_free(buffer); return ret; }
/* Our version of the ossl_ecdh_compute_key replaced in the EC_KEY_METHOD */ static int pkcs11_ec_ckey(void *out, size_t outlen, const EC_POINT *ecpointpeer, const EC_KEY *ecdh, void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen)) { int ret = -1; size_t buflen; unsigned char *buf = NULL; size_t peerbuflen; unsigned char *peerbuf = NULL; const EC_GROUP *ecgroup = NULL; const EC_POINT *ecpoint = NULL; CK_ECDH1_DERIVE_PARAMS ecdh_parms; PKCS11_KEY * key = NULL; key = (PKCS11_KEY *) EC_KEY_get_ex_data(ecdh, ec_key_ex_index); if (key == NULL) { ret -1; goto err; } /* both peer and ecdh use same group parameters */ ecgroup = EC_KEY_get0_group(ecdh); buflen = (EC_GROUP_get_degree(ecgroup) + 7) / 8; peerbuflen = 2*buflen + 1; peerbuf = OPENSSL_malloc(peerbuflen); if (peerbuf == NULL) { ret = -1; goto err; } ecdh_parms.kdf = CKD_NULL; ecdh_parms.ulSharedDataLen = 0; ecdh_parms.pSharedData = NULL; ecdh_parms.ulPublicDataLen = peerbuflen; ret = EC_POINT_point2oct(ecgroup, ecpointpeer, POINT_CONVERSION_UNCOMPRESSED, peerbuf, peerbuflen,NULL); ecdh_parms.ulPublicDataLen = peerbuflen; ecdh_parms.pPublicData = peerbuf; ret = pkcs11_ecdh_derive_internal(&buf, &buflen, CKM_ECDH1_DERIVE, (const void *)&ecdh_parms, NULL, key); if (KDF != 0) { if (KDF(buf, buflen, out, &outlen) == NULL) { ret -1; goto err; } ret = outlen; } else { if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); ret = outlen; } err: OPENSSL_free(buf); return (ret); }
CK_RV PKCS11_Objects_OpenSSL::GetAttributeValue(Cryptoki_Session_Context* pSessionCtx, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { OBJECT_DATA* pObj = PKCS11_Objects_OpenSSL::GetObjectFromHandle(pSessionCtx, hObject); if(pObj == NULL) return CKR_OBJECT_HANDLE_INVALID; if(pObj->Type == CertificateType) { CERT_DATA* pCertData = (CERT_DATA*)pObj->Data; X509* pCert = pCertData->cert; INT32 valLen = 0; for(int i=0; i<(int)ulCount; i++) { switch(pTemplate[i].type) { case CKA_CLASS: *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(CKO_CERTIFICATE); break; case CKA_PRIVATE: *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pCertData->privKeyData.key == NULL ? 0 : 1); valLen = sizeof(INT32); break; case CKA_VALUE_BITS: { *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pCertData->pubKeyData.size); valLen = sizeof(INT32); } break; case CKA_KEY_TYPE: { *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pCertData->pubKeyData.type); valLen = sizeof(UINT32); } break; case CKA_ISSUER: { char* name=X509_NAME_oneline(X509_get_issuer_name(pCert),NULL,0); valLen = TINYCLR_SSL_STRLEN(name) + 1; if(valLen > pTemplate[i].ulValueLen) valLen = pTemplate[i].ulValueLen; hal_strcpy_s((char*)pTemplate[i].pValue, valLen, name); OPENSSL_free(name); } break; case CKA_SUBJECT: { char* subject=X509_NAME_oneline(X509_get_subject_name(pCert),NULL,0); valLen = TINYCLR_SSL_STRLEN(subject) + 1; if(valLen > pTemplate[i].ulValueLen) valLen = pTemplate[i].ulValueLen; hal_strcpy_s((char*)pTemplate[i].pValue, valLen, subject); OPENSSL_free(subject); } break; case CKA_SERIAL_NUMBER: { ASN1_INTEGER* asn = X509_get_serialNumber(pCert); valLen = asn->length; if(valLen > pTemplate[i].ulValueLen) valLen = pTemplate[i].ulValueLen; TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, asn->data, valLen); } break; case CKA_MECHANISM_TYPE: if(pCert->sig_alg != NULL) { int signature_nid; CK_MECHANISM_TYPE type = CKM_VENDOR_DEFINED; signature_nid = OBJ_obj2nid(pCert->sig_alg->algorithm); switch(signature_nid) { case NID_sha1WithRSA: case NID_sha1WithRSAEncryption: //szNid = "1.2.840.113549.1.1.5"; type = CKM_SHA1_RSA_PKCS; break; case NID_md5WithRSA: case NID_md5WithRSAEncryption: //szNid = "1.2.840.113549.1.1.4"; type = CKM_MD5_RSA_PKCS; break; case NID_sha256WithRSAEncryption: //szNid = "1.2.840.113549.1.1.11"; type = CKM_SHA256_RSA_PKCS; break; case NID_sha384WithRSAEncryption: //szNid = "1.2.840.113549.1.1.12"; type = CKM_SHA384_RSA_PKCS; break; case NID_sha512WithRSAEncryption: //szNid = "1.2.840.113549.1.1.13"; type = CKM_SHA512_RSA_PKCS; break; } valLen = sizeof(CK_MECHANISM_TYPE); *(CK_MECHANISM_TYPE*)pTemplate[i].pValue = SwapEndianIfBEc32(type); } break; case CKA_START_DATE: { DATE_TIME_INFO dti; ssl_get_ASN1_UTCTIME(X509_get_notBefore(pCert), &dti); valLen = (INT32)pTemplate[i].ulValueLen; if(valLen > sizeof(dti)) valLen = sizeof(dti); TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, &dti, valLen); } break; case CKA_END_DATE: { DATE_TIME_INFO dti; ssl_get_ASN1_UTCTIME(X509_get_notAfter(pCert), &dti); valLen = pTemplate[i].ulValueLen; if(valLen > sizeof(dti)) valLen = sizeof(dti); TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, &dti, valLen); } break; case CKA_VALUE: { UINT8* pData = (UINT8*)pTemplate[i].pValue; UINT8* pTmp = pData; valLen = i2d_X509(pCert, NULL); if(valLen > pTemplate[i].ulValueLen) return CKR_DEVICE_MEMORY; valLen = i2d_X509(pCert, &pTmp); if(valLen < 0) return CKR_FUNCTION_FAILED; } break; case CKA_VALUE_LEN: *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(valLen); break; default: return CKR_ATTRIBUTE_TYPE_INVALID; } } } else if(pObj->Type == KeyType) { KEY_DATA* pKey = (KEY_DATA*)pObj->Data; int valLen = 0; bool isPrivate = false; for(int i=0; i<(int)ulCount; i++) { switch(pTemplate[i].type) { case CKA_CLASS: *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32((0 != (pKey->attrib & Private) ? CKO_PRIVATE_KEY : 0 != (pKey->attrib & Public) ? CKO_PUBLIC_KEY : CKO_SECRET_KEY)); break; case CKA_MODULUS: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->n, (UINT8*)pTemplate[i].pValue); } break; case CKA_EXPONENT_1: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->dmp1, (UINT8*)pTemplate[i].pValue); } break; case CKA_EXPONENT_2: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->dmq1, (UINT8*)pTemplate[i].pValue); } break; case CKA_COEFFICIENT: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->iqmp, (UINT8*)pTemplate[i].pValue); } break; case CKA_PRIME_1: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->p, (UINT8*)pTemplate[i].pValue); } break; case CKA_PRIME_2: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->q, (UINT8*)pTemplate[i].pValue); } break; case CKA_PRIVATE_EXPONENT: if(pKey->type == CKK_DSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.dsa->priv_key, (UINT8*)pTemplate[i].pValue); } else if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->d, (UINT8*)pTemplate[i].pValue); } break; case CKA_PUBLIC_EXPONENT: if(pKey->type == CKK_DSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.dsa->pub_key, (UINT8*)pTemplate[i].pValue); } else if(pKey->type == CKK_EC) { UINT8 pTmp[66*2+1]; EC_KEY* pEC = ((EVP_PKEY*)pKey->key)->pkey.ec; const EC_POINT* point = EC_KEY_get0_public_key(pEC); valLen = EC_POINT_point2oct(EC_KEY_get0_group(pEC), point, POINT_CONVERSION_UNCOMPRESSED, (UINT8*)pTmp, ARRAYSIZE(pTmp), NULL); if(valLen == 0) return CKR_FUNCTION_FAILED; memmove(pTemplate[i].pValue, &pTmp[1], valLen-1); // remove POINT_CONVERSION_UNCOMPRESSED header byte } else if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->e, (UINT8*)pTemplate[i].pValue); } break; case CKA_PRIME: if(pKey->type == CKK_DSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.dsa->p, (UINT8*)pTemplate[i].pValue); } break; case CKA_SUBPRIME: if(pKey->type == CKK_DSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.dsa->q, (UINT8*)pTemplate[i].pValue); } break; case CKA_BASE: if(pKey->type == CKK_DSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.dsa->g, (UINT8*)pTemplate[i].pValue); } break; case CKA_PRIVATE: isPrivate = 0 != *(INT32*)pTemplate[i].pValue; break; case CKA_KEY_TYPE: *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pKey->type); break; case CKA_VALUE_BITS: *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pKey->size); break; case CKA_VALUE: switch(pKey->type) { case CKK_AES: case CKK_GENERIC_SECRET: { // TODO: Add permissions to export key int len = (pKey->size + 7) / 8; if(len > (INT32)pTemplate[i].ulValueLen) len = (int)pTemplate[i].ulValueLen; TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, pKey->key, len); valLen = len; } break; default: return CKR_ATTRIBUTE_TYPE_INVALID; } break; case CKA_VALUE_LEN: switch(pKey->type) { case CKK_EC: *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(valLen); break; default: return CKR_ATTRIBUTE_TYPE_INVALID; } break; default: return CKR_ATTRIBUTE_TYPE_INVALID; } } } return CKR_OK; }
int verifyRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const uint8_t *pSigc, const uint8_t *pSigr) { if (fDebugRingSig) { // LogPrintf("%s size %d\n", __func__, nRingSize); // happens often }; int rv = 0; BN_CTX_start(bnCtx); BIGNUM *bnT = BN_CTX_get(bnCtx); BIGNUM *bnH = BN_CTX_get(bnCtx); BIGNUM *bnC = BN_CTX_get(bnCtx); BIGNUM *bnR = BN_CTX_get(bnCtx); BIGNUM *bnSum = BN_CTX_get(bnCtx); EC_POINT *ptT1 = NULL; EC_POINT *ptT2 = NULL; EC_POINT *ptT3 = NULL; EC_POINT *ptPk = NULL; EC_POINT *ptKi = NULL; EC_POINT *ptL = NULL; EC_POINT *ptR = NULL; EC_POINT *ptSi = NULL; uint8_t tempData[66]; // hold raw point data to hash uint256 commitHash; CHashWriter ssCommitHash(SER_GETHASH, PROTOCOL_VERSION); ssCommitHash << txnHash; // zero sum if (!bnSum || !(BN_zero(bnSum))) { LogPrintf("%s: BN_zero failed.\n", __func__); rv = 1; goto End; }; if ( !(ptT1 = EC_POINT_new(ecGrp)) || !(ptT2 = EC_POINT_new(ecGrp)) || !(ptT3 = EC_POINT_new(ecGrp)) || !(ptPk = EC_POINT_new(ecGrp)) || !(ptKi = EC_POINT_new(ecGrp)) || !(ptL = EC_POINT_new(ecGrp)) || !(ptSi = EC_POINT_new(ecGrp)) || !(ptR = EC_POINT_new(ecGrp))) { LogPrintf("%s: EC_POINT_new failed.\n", __func__); rv = 1; goto End; }; // get keyimage as point if (!(bnT = BN_bin2bn(&keyImage[0], EC_COMPRESSED_SIZE, bnT)) || !(ptKi) || !(ptKi = EC_POINT_bn2point(ecGrp, bnT, ptKi, bnCtx))) { LogPrintf("%s: extract ptKi failed.\n", __func__); rv = 1; goto End; }; for (int i = 0; i < nRingSize; ++i) { // Li = ci * Pi + ri * G // Ri = ci * I + ri * Hp(Pi) if ( !bnC || !(bnC = BN_bin2bn(&pSigc[i * EC_SECRET_SIZE], EC_SECRET_SIZE, bnC)) || !bnR || !(bnR = BN_bin2bn(&pSigr[i * EC_SECRET_SIZE], EC_SECRET_SIZE, bnR))) { LogPrintf("%s: extract bnC and bnR failed.\n", __func__); rv = 1; goto End; }; // get Pk i as point if (!(bnT = BN_bin2bn(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT)) || !(ptPk) || !(ptPk = EC_POINT_bn2point(ecGrp, bnT, ptPk, bnCtx))) { LogPrintf("%s: extract ptPk failed.\n", __func__); rv = 1; goto End; }; // ptT1 = ci * Pi if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptPk, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT2 = ri * G if (!EC_POINT_mul(ecGrp, ptT2, bnR, NULL, NULL, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptL = ptT1 + ptT2 if (!EC_POINT_add(ecGrp, ptL, ptT1, ptT2, bnCtx)) { LogPrintf("%s: EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; // ptT3 = Hp(Pi) if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT3) != 0) { LogPrintf("%s: hashToEC failed.\n", __func__); rv = 1; goto End; }; // DEBUGGING: ------- check if we can find the signer... // ptSi = Pi * bnT if ((!EC_POINT_mul(ecGrp, ptSi, NULL, ptPk, bnT, bnCtx) || false) && (rv = errorN(1, "%s: EC_POINT_mul failed.1", __func__))) goto End; if (0 == EC_POINT_cmp(ecGrp, ptSi, ptKi, bnCtx) ) LogPrintf("signer is index %d\n", i); // DEBUGGING: - End - check if we can find the signer... // ptT1 = k1 * I if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT2 = k2 * ptT3 if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnR, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptR = ptT1 + ptT2 if (!EC_POINT_add(ecGrp, ptR, ptT1, ptT2, bnCtx)) { LogPrintf("%s: EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; // sum = (sum + ci) % N if (!BN_mod_add(bnSum, bnSum, bnC, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_add failed.\n", __func__); rv = 1; goto End; }; // -- add ptL and ptR to hash if ( !(EC_POINT_point2oct(ecGrp, ptL, POINT_CONVERSION_COMPRESSED, &tempData[0], 33, bnCtx) == (int) EC_COMPRESSED_SIZE) || !(EC_POINT_point2oct(ecGrp, ptR, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE)) { LogPrintf("%s: extract ptL and ptR failed.\n", __func__); rv = 1; goto End; }; ssCommitHash.write((const char*)&tempData[0], 66); }; commitHash = ssCommitHash.GetHash(); if (!(bnH) || !(bnH = BN_bin2bn(commitHash.begin(), EC_SECRET_SIZE, bnH))) { LogPrintf("%s: commitHash -> bnH failed.\n", __func__); rv = 1; goto End; }; if (!BN_mod(bnH, bnH, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod failed.\n", __func__); rv = 1; goto End; }; // bnT = (bnH - bnSum) % N if (!BN_mod_sub(bnT, bnH, bnSum, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_sub failed.\n", __func__); rv = 1; goto End; }; // test bnT == 0 (bnSum == bnH) if (!BN_is_zero(bnT)) { LogPrintf("%s: signature does not verify.\n", __func__); rv = 2; }; End: EC_POINT_free(ptT1); EC_POINT_free(ptT2); EC_POINT_free(ptT3); EC_POINT_free(ptPk); EC_POINT_free(ptKi); EC_POINT_free(ptL); EC_POINT_free(ptR); EC_POINT_free(ptSi); BN_CTX_end(bnCtx); return rv; };
int sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key) { #ifdef ENABLE_OPENSSL EVP_PKEY *pk = (EVP_PKEY *)evp_key; switch (pk->type) { case EVP_PKEY_RSA: { struct sc_pkcs15_prkey_rsa *dst = &pkcs15_key->u.rsa; RSA *src = EVP_PKEY_get1_RSA(pk); pkcs15_key->algorithm = SC_ALGORITHM_RSA; if (!sc_pkcs15_convert_bignum(&dst->modulus, src->n) || !sc_pkcs15_convert_bignum(&dst->exponent, src->e) || !sc_pkcs15_convert_bignum(&dst->d, src->d) || !sc_pkcs15_convert_bignum(&dst->p, src->p) || !sc_pkcs15_convert_bignum(&dst->q, src->q)) return SC_ERROR_NOT_SUPPORTED; if (src->iqmp && src->dmp1 && src->dmq1) { sc_pkcs15_convert_bignum(&dst->iqmp, src->iqmp); sc_pkcs15_convert_bignum(&dst->dmp1, src->dmp1); sc_pkcs15_convert_bignum(&dst->dmq1, src->dmq1); } RSA_free(src); break; } case EVP_PKEY_DSA: { struct sc_pkcs15_prkey_dsa *dst = &pkcs15_key->u.dsa; DSA *src = EVP_PKEY_get1_DSA(pk); pkcs15_key->algorithm = SC_ALGORITHM_DSA; sc_pkcs15_convert_bignum(&dst->pub, src->pub_key); sc_pkcs15_convert_bignum(&dst->p, src->p); sc_pkcs15_convert_bignum(&dst->q, src->q); sc_pkcs15_convert_bignum(&dst->g, src->g); sc_pkcs15_convert_bignum(&dst->priv, src->priv_key); DSA_free(src); break; } #if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) case NID_id_GostR3410_2001: { struct sc_pkcs15_prkey_gostr3410 *dst = &pkcs15_key->u.gostr3410; EC_KEY *src = EVP_PKEY_get0(pk); assert(src); pkcs15_key->algorithm = SC_ALGORITHM_GOSTR3410; assert(EC_KEY_get0_private_key(src)); sc_pkcs15_convert_bignum(&dst->d, EC_KEY_get0_private_key(src)); break; } case EVP_PKEY_EC: { struct sc_pkcs15_prkey_ec *dst = &pkcs15_key->u.ec; EC_KEY *src = NULL; const EC_GROUP *grp = NULL; unsigned char buf[255]; size_t buflen = 255; int nid; src = EVP_PKEY_get0(pk); assert(src); assert(EC_KEY_get0_private_key(src)); assert(EC_KEY_get0_public_key(src)); pkcs15_key->algorithm = SC_ALGORITHM_EC; if (!sc_pkcs15_convert_bignum(&dst->privateD, EC_KEY_get0_private_key(src))) return SC_ERROR_INCOMPATIBLE_KEY; grp = EC_KEY_get0_group(src); if(grp == 0) return SC_ERROR_INCOMPATIBLE_KEY; /* get curve name */ nid = EC_GROUP_get_curve_name(grp); if(nid != 0) dst->params.named_curve = strdup(OBJ_nid2sn(nid)); /* Decode EC_POINT from a octet string */ buflen = EC_POINT_point2oct(grp, (const EC_POINT *) EC_KEY_get0_public_key(src), POINT_CONVERSION_UNCOMPRESSED, buf, buflen, NULL); if (!buflen) return SC_ERROR_INCOMPATIBLE_KEY; /* copy the public key */ dst->ecpointQ.value = malloc(buflen); memcpy(dst->ecpointQ.value, buf, buflen); dst->ecpointQ.len = buflen; /* calculate the field length */ dst->params.field_length = (buflen - 1) / 2 * 8; /* Octetstring may need leading zeros if BN is to short */ if (dst->privateD.len < dst->params.field_length/8) { size_t d = dst->params.field_length/8 - dst->privateD.len; dst->privateD.data = realloc(dst->privateD.data, dst->privateD.len + d); if (!dst->privateD.data) return SC_ERROR_OUT_OF_MEMORY; memmove(dst->privateD.data + d, dst->privateD.data, dst->privateD.len); memset(dst->privateD.data, 0, d); dst->privateD.len += d; } break; } #endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) */ default: return SC_ERROR_NOT_SUPPORTED; } return SC_SUCCESS; #else return SC_ERROR_NOT_IMPLEMENTED; #endif }
int sc_pkcs15_convert_pubkey(struct sc_pkcs15_pubkey *pkcs15_key, void *evp_key) { #ifdef ENABLE_OPENSSL EVP_PKEY *pk = (EVP_PKEY *)evp_key; switch (pk->type) { case EVP_PKEY_RSA: { struct sc_pkcs15_pubkey_rsa *dst = &pkcs15_key->u.rsa; RSA *src = EVP_PKEY_get1_RSA(pk); pkcs15_key->algorithm = SC_ALGORITHM_RSA; if (!sc_pkcs15_convert_bignum(&dst->modulus, src->n) || !sc_pkcs15_convert_bignum(&dst->exponent, src->e)) return SC_ERROR_INVALID_DATA; RSA_free(src); break; } case EVP_PKEY_DSA: { struct sc_pkcs15_pubkey_dsa *dst = &pkcs15_key->u.dsa; DSA *src = EVP_PKEY_get1_DSA(pk); pkcs15_key->algorithm = SC_ALGORITHM_DSA; sc_pkcs15_convert_bignum(&dst->pub, src->pub_key); sc_pkcs15_convert_bignum(&dst->p, src->p); sc_pkcs15_convert_bignum(&dst->q, src->q); sc_pkcs15_convert_bignum(&dst->g, src->g); DSA_free(src); break; } #if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) case NID_id_GostR3410_2001: { struct sc_pkcs15_pubkey_gostr3410 *dst = &pkcs15_key->u.gostr3410; EC_KEY *eckey = EVP_PKEY_get0(pk); const EC_POINT *point; BIGNUM *X, *Y; int r = 0; assert(eckey); point = EC_KEY_get0_public_key(eckey); if (!point) return SC_ERROR_INTERNAL; X = BN_new(); Y = BN_new(); if (X && Y && EC_KEY_get0_group(eckey)) r = EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(eckey), point, X, Y, NULL); if (r == 1) { dst->xy.len = BN_num_bytes(X) + BN_num_bytes(Y); dst->xy.data = malloc(dst->xy.len); if (dst->xy.data) { BN_bn2bin(Y, dst->xy.data); BN_bn2bin(X, dst->xy.data + BN_num_bytes(Y)); r = sc_mem_reverse(dst->xy.data, dst->xy.len); if (!r) r = 1; pkcs15_key->algorithm = SC_ALGORITHM_GOSTR3410; } else r = -1; } BN_free(X); BN_free(Y); if (r != 1) return SC_ERROR_INTERNAL; break; } case EVP_PKEY_EC: { struct sc_pkcs15_pubkey_ec *dst = &pkcs15_key->u.ec; EC_KEY *src = NULL; const EC_GROUP *grp = NULL; unsigned char buf[255]; size_t buflen = 255; int nid; src = EVP_PKEY_get0(pk); assert(src); assert(EC_KEY_get0_public_key(src)); pkcs15_key->algorithm = SC_ALGORITHM_EC; grp = EC_KEY_get0_group(src); if(grp == 0) return SC_ERROR_INCOMPATIBLE_KEY; /* Decode EC_POINT from a octet string */ buflen = EC_POINT_point2oct(grp, (const EC_POINT *) EC_KEY_get0_public_key(src), POINT_CONVERSION_UNCOMPRESSED, buf, buflen, NULL); /* get curve name */ nid = EC_GROUP_get_curve_name(grp); if(nid != 0) { const char *name = OBJ_nid2sn(nid); if(sizeof(name) > 0) dst->params.named_curve = strdup(name); } /* copy the public key */ if (buflen > 0) { dst->ecpointQ.value = malloc(buflen); memcpy(dst->ecpointQ.value, buf, buflen); dst->ecpointQ.len = buflen; /* calculate the field length */ dst->params.field_length = (buflen - 1) / 2 * 8; } else return SC_ERROR_INCOMPATIBLE_KEY; break; } #endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) */ default: return SC_ERROR_NOT_SUPPORTED; } return SC_SUCCESS; #else return SC_ERROR_NOT_IMPLEMENTED; #endif }
SM2_CIPHERTEXT_VALUE *SM2_do_encrypt(const EVP_MD *kdf_md, const EVP_MD *mac_md, const unsigned char *in, size_t inlen, EC_KEY *ec_key) { int ok = 0; SM2_CIPHERTEXT_VALUE *cv = NULL; const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key); const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key); KDF_FUNC kdf = KDF_get_x9_63(kdf_md); EC_POINT *point = NULL; BIGNUM *n = NULL; BIGNUM *h = NULL; BIGNUM *k = NULL; BN_CTX *bn_ctx = NULL; EVP_MD_CTX *md_ctx = NULL; unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1]; int nbytes; size_t len; int i; if (!ec_group || !pub_key) { goto end; } if (!kdf) { goto end; } /* init ciphertext_value */ if (!(cv = OPENSSL_malloc(sizeof(SM2_CIPHERTEXT_VALUE)))) { goto end; } bzero(cv, sizeof(SM2_CIPHERTEXT_VALUE)); cv->ephem_point = EC_POINT_new(ec_group); cv->ciphertext = OPENSSL_malloc(inlen); cv->ciphertext_size = inlen; if (!cv->ephem_point || !cv->ciphertext) { goto end; } point = EC_POINT_new(ec_group); n = BN_new(); h = BN_new(); k = BN_new(); bn_ctx = BN_CTX_new(); md_ctx = EVP_MD_CTX_create(); if (!point || !n || !h || !k || !bn_ctx || !md_ctx) { goto end; } /* init ec domain parameters */ if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) { goto end; } if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) { goto end; } nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8; OPENSSL_assert(nbytes == BN_num_bytes(n)); #if 0 /* check sm2 curve and md is 256 bits */ OPENSSL_assert(nbytes == 32); OPENSSL_assert(EVP_MD_size(kdf_md) == 32); OPENSSL_assert(EVP_MD_size(mac_md) == 32); #endif do { /* A1: rand k in [1, n-1] */ do { BN_rand_range(k, n); } while (BN_is_zero(k)); /* A2: C1 = [k]G = (x1, y1) */ if (!EC_POINT_mul(ec_group, cv->ephem_point, k, NULL, NULL, bn_ctx)) { goto end; } /* A3: check [h]P_B != O */ if (!EC_POINT_mul(ec_group, point, NULL, pub_key, h, bn_ctx)) { goto end; } if (EC_POINT_is_at_infinity(ec_group, point)) { goto end; } /* A4: compute ECDH [k]P_B = (x2, y2) */ if (!EC_POINT_mul(ec_group, point, NULL, pub_key, k, bn_ctx)) { goto end; } if (!(len = EC_POINT_point2oct(ec_group, point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { goto end; } OPENSSL_assert(len == nbytes * 2 + 1); /* A5: t = KDF(x2 || y2, klen) */ kdf(buf + 1, len - 1, cv->ciphertext, &cv->ciphertext_size); for (i = 0; i < cv->ciphertext_size; i++) { if (cv->ciphertext[i]) { break; } } if (i == cv->ciphertext_size) { continue; } break; } while (1); /* A6: C2 = M xor t */ for (i = 0; i < inlen; i++) { cv->ciphertext[i] ^= in[i]; } /* A7: C3 = Hash(x2 || M || y2) */ if (!EVP_DigestInit_ex(md_ctx, mac_md, NULL)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) { goto end; } if (!EVP_DigestUpdate(md_ctx, in, inlen)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) { goto end; } if (!EVP_DigestFinal_ex(md_ctx, cv->mactag, &cv->mactag_size)) { goto end; } ok = 1; end: if (!ok && cv) { SM2_CIPHERTEXT_VALUE_free(cv); cv = NULL; } if (point) EC_POINT_free(point); if (n) BN_free(n); if (h) BN_free(h); if (k) BN_free(k); if (bn_ctx) BN_CTX_free(bn_ctx); if (md_ctx) EVP_MD_CTX_destroy(md_ctx); return cv; }
void char2_field_tests() { BN_CTX *ctx = NULL; BIGNUM *p, *a, *b; EC_GROUP *group; EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 = NULL, *C2_K571 = NULL; EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 = NULL, *C2_B571 = NULL; EC_POINT *P, *Q, *R; BIGNUM *x, *y, *z, *cof; unsigned char buf[100]; size_t i, len; int k; #if 1 /* optional */ ctx = BN_CTX_new(); if (!ctx) ABORT; #endif p = BN_new(); a = BN_new(); b = BN_new(); if (!p || !a || !b) ABORT; if (!BN_hex2bn(&p, "13")) ABORT; if (!BN_hex2bn(&a, "3")) ABORT; if (!BN_hex2bn(&b, "1")) ABORT; group = EC_GROUP_new(EC_GF2m_simple_method()); /* applications should use EC_GROUP_new_curve_GF2m * so that the library gets to choose the EC_METHOD */ if (!group) ABORT; if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT; { EC_GROUP *tmp; tmp = EC_GROUP_new(EC_GROUP_method_of(group)); if (!tmp) ABORT; if (!EC_GROUP_copy(tmp, group)) ABORT; EC_GROUP_free(group); group = tmp; } if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) ABORT; fprintf(stdout, "Curve defined by Weierstrass equation\n y^2 + x*y = x^3 + a*x^2 + b (mod 0x"); BN_print_fp(stdout, p); fprintf(stdout, ")\n a = 0x"); BN_print_fp(stdout, a); fprintf(stdout, "\n b = 0x"); BN_print_fp(stdout, b); fprintf(stdout, "\n(0x... means binary polynomial)\n"); P = EC_POINT_new(group); Q = EC_POINT_new(group); R = EC_POINT_new(group); if (!P || !Q || !R) ABORT; if (!EC_POINT_set_to_infinity(group, P)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; buf[0] = 0; if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; x = BN_new(); y = BN_new(); z = BN_new(); cof = BN_new(); if (!x || !y || !z || !cof) ABORT; if (!BN_hex2bn(&x, "6")) ABORT; /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx)) ABORT; #else if (!BN_hex2bn(&y, "8")) ABORT; if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT; #endif if (!EC_POINT_is_on_curve(group, Q, ctx)) { /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT; #endif fprintf(stderr, "Point is not on curve: x = 0x"); BN_print_fp(stderr, x); fprintf(stderr, ", y = 0x"); BN_print_fp(stderr, y); fprintf(stderr, "\n"); ABORT; } fprintf(stdout, "A cyclic subgroup:\n"); k = 100; do { if (k-- == 0) ABORT; if (EC_POINT_is_at_infinity(group, P)) fprintf(stdout, " point at infinity\n"); else { if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; fprintf(stdout, " x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, ", y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); } if (!EC_POINT_copy(R, P)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; } while (!EC_POINT_is_at_infinity(group, P)); if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "Generator as octet string, compressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); #endif len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octet string, hybrid form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); #endif fprintf(stdout, "\n"); if (!EC_POINT_invert(group, P, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; /* Curve K-163 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-163", "0800000000000000000000000000000000000000C9", "1", "1", "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8", "0289070FB05D38FF58321F2E800536D538CCDAA3D9", 1, "04000000000000000000020108A2E0CC0D99F8A5EF", "2", 163, C2_K163 ); /* Curve B-163 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-163", "0800000000000000000000000000000000000000C9", "1", "020A601907B8C953CA1481EB10512F78744A3205FD", "03F0EBA16286A2D57EA0991168D4994637E8343E36", "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", 1, "040000000000000000000292FE77E70C12A4234C33", "2", 163, C2_B163 ); /* Curve K-233 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-233", "020000000000000000000000000000000000000004000000000000000001", "0", "1", "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126", "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", 0, "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", "4", 233, C2_K233 ); /* Curve B-233 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-233", "020000000000000000000000000000000000000004000000000000000001", "000000000000000000000000000000000000000000000000000000000001", "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B", "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", 1, "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", "2", 233, C2_B233 ); /* Curve K-283 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-283", "0800000000000000000000000000000000000000000000000000000000000000000010A1", "0", "1", "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836", "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", 0, "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", "4", 283, C2_K283 ); /* Curve B-283 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-283", "0800000000000000000000000000000000000000000000000000000000000000000010A1", "000000000000000000000000000000000000000000000000000000000000000000000001", "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053", "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", 1, "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", "2", 283, C2_B283 ); /* Curve K-409 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-409", "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", "0", "1", "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746", "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", 1, "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", "4", 409, C2_K409 ); /* Curve B-409 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-409", "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7", "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", 1, "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", "2", 409, C2_B409 ); /* Curve K-571 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-571", "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", "0", "1", "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972", "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", 0, "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", "4", 571, C2_K571 ); /* Curve B-571 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-571", "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19", "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", 1, "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", "2", 571, C2_B571 ); /* more tests using the last curve */ if (!EC_POINT_copy(Q, P)) ABORT; if (EC_POINT_is_at_infinity(group, Q)) ABORT; if (!EC_POINT_dbl(group, P, P, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */ if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT; if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */ { const EC_POINT *points[3]; const BIGNUM *scalars[3]; if (EC_POINT_is_at_infinity(group, Q)) ABORT; points[0] = Q; points[1] = Q; points[2] = Q; if (!BN_add(y, z, BN_value_one())) ABORT; if (BN_is_odd(y)) ABORT; if (!BN_rshift1(y, y)) ABORT; scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ scalars[1] = y; fprintf(stdout, "combined multiplication ..."); fflush(stdout); /* z is still the group order */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT; if (!BN_add(z, z, y)) ABORT; BN_set_negative(z, 1); scalars[0] = y; scalars[1] = z; /* z = -(order + y) */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT; if (!BN_add(z, x, y)) ABORT; BN_set_negative(z, 1); scalars[0] = x; scalars[1] = y; scalars[2] = z; /* z = -(x+y) */ if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, " ok\n\n"); } #if 0 timings(C2_K163, TIMING_BASE_PT, ctx); timings(C2_K163, TIMING_RAND_PT, ctx); timings(C2_K163, TIMING_SIMUL, ctx); timings(C2_B163, TIMING_BASE_PT, ctx); timings(C2_B163, TIMING_RAND_PT, ctx); timings(C2_B163, TIMING_SIMUL, ctx); timings(C2_K233, TIMING_BASE_PT, ctx); timings(C2_K233, TIMING_RAND_PT, ctx); timings(C2_K233, TIMING_SIMUL, ctx); timings(C2_B233, TIMING_BASE_PT, ctx); timings(C2_B233, TIMING_RAND_PT, ctx); timings(C2_B233, TIMING_SIMUL, ctx); timings(C2_K283, TIMING_BASE_PT, ctx); timings(C2_K283, TIMING_RAND_PT, ctx); timings(C2_K283, TIMING_SIMUL, ctx); timings(C2_B283, TIMING_BASE_PT, ctx); timings(C2_B283, TIMING_RAND_PT, ctx); timings(C2_B283, TIMING_SIMUL, ctx); timings(C2_K409, TIMING_BASE_PT, ctx); timings(C2_K409, TIMING_RAND_PT, ctx); timings(C2_K409, TIMING_SIMUL, ctx); timings(C2_B409, TIMING_BASE_PT, ctx); timings(C2_B409, TIMING_RAND_PT, ctx); timings(C2_B409, TIMING_SIMUL, ctx); timings(C2_K571, TIMING_BASE_PT, ctx); timings(C2_K571, TIMING_RAND_PT, ctx); timings(C2_K571, TIMING_SIMUL, ctx); timings(C2_B571, TIMING_BASE_PT, ctx); timings(C2_B571, TIMING_RAND_PT, ctx); timings(C2_B571, TIMING_SIMUL, ctx); #endif if (ctx) BN_CTX_free(ctx); BN_free(p); BN_free(a); BN_free(b); EC_GROUP_free(group); EC_POINT_free(P); EC_POINT_free(Q); EC_POINT_free(R); BN_free(x); BN_free(y); BN_free(z); BN_free(cof); if (C2_K163) EC_GROUP_free(C2_K163); if (C2_B163) EC_GROUP_free(C2_B163); if (C2_K233) EC_GROUP_free(C2_K233); if (C2_B233) EC_GROUP_free(C2_B233); if (C2_K283) EC_GROUP_free(C2_K283); if (C2_B283) EC_GROUP_free(C2_B283); if (C2_K409) EC_GROUP_free(C2_K409); if (C2_B409) EC_GROUP_free(C2_B409); if (C2_K571) EC_GROUP_free(C2_K571); if (C2_B571) EC_GROUP_free(C2_B571); }
int verifyRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const data_chunk &sigC, const uint8_t *pSigS) { // https://bitcointalk.org/index.php?topic=972541.msg10619684 // forall_{i=1..n} compute e_i=s_i*G+c_i*P_i and E_i=s_i*H(P_i)+c_i*I_j and c_{i+1}=h(P_1,...,P_n,e_i,E_i) // check c_{n+1}=c_1 if (fDebugRingSig) { //LogPrintf("%s size %d\n", __func__, nRingSize); // happens often }; if (sigC.size() != EC_SECRET_SIZE) return errorN(1, "%s: sigC size != EC_SECRET_SIZE.", __func__); if (keyImage.size() != EC_COMPRESSED_SIZE) return errorN(1, "%s: keyImage size != EC_COMPRESSED_SIZE.", __func__); int rv = 0; uint256 tmpPkHash; uint256 tmpHash; uint8_t tempData[66]; // hold raw point data to hash CHashWriter ssPkHash(SER_GETHASH, PROTOCOL_VERSION); CHashWriter ssCjHash(SER_GETHASH, PROTOCOL_VERSION); for (int i = 0; i < nRingSize; ++i) { ssPkHash.write((const char*)&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE); }; tmpPkHash = ssPkHash.GetHash(); BN_CTX_start(bnCtx); BIGNUM *bnC = BN_CTX_get(bnCtx); BIGNUM *bnC1 = BN_CTX_get(bnCtx); BIGNUM *bnT = BN_CTX_get(bnCtx); BIGNUM *bnS = BN_CTX_get(bnCtx); EC_POINT *ptKi = NULL; EC_POINT *ptT1 = NULL; EC_POINT *ptT2 = NULL; EC_POINT *ptT3 = NULL; EC_POINT *ptPk = NULL; EC_POINT *ptSi = NULL; if ( !(ptKi = EC_POINT_new(ecGrp)) || !(ptT1 = EC_POINT_new(ecGrp)) || !(ptT2 = EC_POINT_new(ecGrp)) || !(ptT3 = EC_POINT_new(ecGrp)) || !(ptPk = EC_POINT_new(ecGrp)) || !(ptSi = EC_POINT_new(ecGrp))) { LogPrintf("%s: EC_POINT_new failed.\n", __func__); rv = 1; goto End; }; // get keyimage as point if (!EC_POINT_oct2point(ecGrp, ptKi, &keyImage[0], EC_COMPRESSED_SIZE, bnCtx)) { LogPrintf("%s: extract ptKi failed.\n", __func__); rv = 1; goto End; }; if (!bnC1 || !BN_bin2bn(&sigC[0], EC_SECRET_SIZE, bnC1)) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; if (!BN_copy(bnC, bnC1)) { LogPrintf("%s: BN_copy failed.\n", __func__); rv = 1; goto End; }; for (int i = 0; i < nRingSize; ++i) { if (!bnS || !(BN_bin2bn(&pSigS[i * EC_SECRET_SIZE], EC_SECRET_SIZE, bnS))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; // ptT2 <- pk if (!EC_POINT_oct2point(ecGrp, ptPk, &pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnCtx)) { LogPrintf("%s: EC_POINT_oct2point failed.\n", __func__); rv = 1; goto End; }; // ptT1 = e_i=s_i*G+c_i*P_i if (!EC_POINT_mul(ecGrp, ptT1, bnS, ptPk, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; if (!(EC_POINT_point2oct(ecGrp, ptT1, POINT_CONVERSION_COMPRESSED, &tempData[0], 33, bnCtx) == (int) EC_COMPRESSED_SIZE)) { LogPrintf("%s: extract ptT1 failed.\n", __func__); rv = 1; goto End; }; // ptT2 =E_i=s_i*H(P_i)+c_i*I_j // ptT2 =H(P_i) if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT2) != 0) { LogPrintf("%s: hashToEC failed.\n", __func__); rv = 1; goto End; }; // DEBUGGING: ------- check if we can find the signer... // ptSi = Pi * bnT if ((!EC_POINT_mul(ecGrp, ptSi, NULL, ptPk, bnT, bnCtx) || false) && (rv = errorN(1, "%s: EC_POINT_mul failed.", __func__))) goto End; if (0 == EC_POINT_cmp(ecGrp, ptSi, ptKi, bnCtx) ) LogPrintf("signer is index %d\n", i); // DEBUGGING: - End - check if we can find the signer... // ptT3 = s_i*ptT2 if (!EC_POINT_mul(ecGrp, ptT3, NULL, ptT2, bnS, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT1 = c_i*I_j if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT2 = ptT3 + ptT1 if (!EC_POINT_add(ecGrp, ptT2, ptT3, ptT1, bnCtx)) { LogPrintf("%s: EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; if (!(EC_POINT_point2oct(ecGrp, ptT2, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE)) { LogPrintf("%s: extract ptT2 failed.\n", __func__); rv = 1; goto End; }; CHashWriter ssCHash(SER_GETHASH, PROTOCOL_VERSION); ssCHash.write((const char*)tmpPkHash.begin(), 32); ssCHash.write((const char*)&tempData[0], 66); tmpHash = ssCHash.GetHash(); if (!bnC || !(BN_bin2bn(tmpHash.begin(), EC_SECRET_SIZE, bnC)) || !BN_mod(bnC, bnC, bnOrder, bnCtx)) { LogPrintf("%s: tmpHash -> bnC failed.\n", __func__); rv = 1; goto End; }; }; // bnT = (bnC - bnC1) % N if (!BN_mod_sub(bnT, bnC, bnC1, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_sub failed.\n", __func__); rv = 1; goto End; }; // test bnT == 0 (bnC == bnC1) if (!BN_is_zero(bnT)) { LogPrintf("%s: signature does not verify.\n", __func__); rv = 2; }; End: BN_CTX_end(bnCtx); EC_POINT_free(ptKi); EC_POINT_free(ptT1); EC_POINT_free(ptT2); EC_POINT_free(ptT3); EC_POINT_free(ptPk); EC_POINT_free(ptSi); return rv; };
void prime_field_tests() { BN_CTX *ctx = NULL; BIGNUM *p, *a, *b; EC_GROUP *group; EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL; EC_POINT *P, *Q, *R; BIGNUM *x, *y, *z; unsigned char buf[100]; size_t i, len; int k; #if 1 /* optional */ ctx = BN_CTX_new(); if (!ctx) ABORT; #endif p = BN_new(); a = BN_new(); b = BN_new(); if (!p || !a || !b) ABORT; if (!BN_hex2bn(&p, "17")) ABORT; if (!BN_hex2bn(&a, "1")) ABORT; if (!BN_hex2bn(&b, "1")) ABORT; group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp * so that the library gets to choose the EC_METHOD */ if (!group) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; { EC_GROUP *tmp; tmp = EC_GROUP_new(EC_GROUP_method_of(group)); if (!tmp) ABORT; if (!EC_GROUP_copy(tmp, group)) ABORT; EC_GROUP_free(group); group = tmp; } if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) ABORT; fprintf(stdout, "Curve defined by Weierstrass equation\n y^2 = x^3 + a*x + b (mod 0x"); BN_print_fp(stdout, p); fprintf(stdout, ")\n a = 0x"); BN_print_fp(stdout, a); fprintf(stdout, "\n b = 0x"); BN_print_fp(stdout, b); fprintf(stdout, "\n"); P = EC_POINT_new(group); Q = EC_POINT_new(group); R = EC_POINT_new(group); if (!P || !Q || !R) ABORT; if (!EC_POINT_set_to_infinity(group, P)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; buf[0] = 0; if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; x = BN_new(); y = BN_new(); z = BN_new(); if (!x || !y || !z) ABORT; if (!BN_hex2bn(&x, "D")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, Q, ctx)) { if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT; fprintf(stderr, "Point is not on curve: x = 0x"); BN_print_fp(stderr, x); fprintf(stderr, ", y = 0x"); BN_print_fp(stderr, y); fprintf(stderr, "\n"); ABORT; } fprintf(stdout, "A cyclic subgroup:\n"); k = 100; do { if (k-- == 0) ABORT; if (EC_POINT_is_at_infinity(group, P)) fprintf(stdout, " point at infinity\n"); else { if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, " x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, ", y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); } if (!EC_POINT_copy(R, P)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; #if 0 /* optional */ { EC_POINT *points[3]; points[0] = R; points[1] = Q; points[2] = P; if (!EC_POINTs_make_affine(group, 2, points, ctx)) ABORT; } #endif } while (!EC_POINT_is_at_infinity(group, P)); if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "Generator as octect string, compressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octect string, uncompressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octect string, hybrid form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT; fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n X = 0x"); BN_print_fp(stdout, x); fprintf(stdout, ", Y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, ", Z = 0x"); BN_print_fp(stdout, z); fprintf(stdout, "\n"); if (!EC_POINT_invert(group, P, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; /* Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, 2000) * -- not a NIST curve, but commonly used */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) ABORT; if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT; if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT; if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 160) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_160, group)) ABORT; /* Curve P-192 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-192 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 192) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_192, group)) ABORT; /* Curve P-224 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT; if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-224 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 224) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_224, group)) ABORT; /* Curve P-256 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E" "84F3B9CAC2FC632551")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-256 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 256) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_256, group)) ABORT; /* Curve P-384 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141" "120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B" "9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-384 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14" "7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 384) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_384, group)) ABORT; /* Curve P-521 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B" "315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573" "DF883D2C34F1EF451FD46B503F00")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F" "B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B" "3C1856A429BF97E7E31C2E5BD66")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5" "C9B8899C47AEBB6FB71E91386409")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-521 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579" "B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C" "7086A272C24088BE94769FD16650")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 521) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_521, group)) ABORT; /* more tests using the last curve */ if (!EC_POINT_copy(Q, P)) ABORT; if (EC_POINT_is_at_infinity(group, Q)) ABORT; if (!EC_POINT_dbl(group, P, P, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */ if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT; if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */ { const EC_POINT *points[3]; const BIGNUM *scalars[3]; if (EC_POINT_is_at_infinity(group, Q)) ABORT; points[0] = Q; points[1] = Q; points[2] = Q; if (!BN_add(y, z, BN_value_one())) ABORT; if (BN_is_odd(y)) ABORT; if (!BN_rshift1(y, y)) ABORT; scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ scalars[1] = y; fprintf(stdout, "combined multiplication ..."); fflush(stdout); /* z is still the group order */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT; if (!BN_add(z, z, y)) ABORT; BN_set_negative(z, 1); scalars[0] = y; scalars[1] = z; /* z = -(order + y) */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT; if (!BN_add(z, x, y)) ABORT; BN_set_negative(z, 1); scalars[0] = x; scalars[1] = y; scalars[2] = z; /* z = -(x+y) */ if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, " ok\n\n"); } #if 0 timings(P_160, TIMING_BASE_PT, ctx); timings(P_160, TIMING_RAND_PT, ctx); timings(P_160, TIMING_SIMUL, ctx); timings(P_192, TIMING_BASE_PT, ctx); timings(P_192, TIMING_RAND_PT, ctx); timings(P_192, TIMING_SIMUL, ctx); timings(P_224, TIMING_BASE_PT, ctx); timings(P_224, TIMING_RAND_PT, ctx); timings(P_224, TIMING_SIMUL, ctx); timings(P_256, TIMING_BASE_PT, ctx); timings(P_256, TIMING_RAND_PT, ctx); timings(P_256, TIMING_SIMUL, ctx); timings(P_384, TIMING_BASE_PT, ctx); timings(P_384, TIMING_RAND_PT, ctx); timings(P_384, TIMING_SIMUL, ctx); timings(P_521, TIMING_BASE_PT, ctx); timings(P_521, TIMING_RAND_PT, ctx); timings(P_521, TIMING_SIMUL, ctx); #endif if (ctx) BN_CTX_free(ctx); BN_free(p); BN_free(a); BN_free(b); EC_GROUP_free(group); EC_POINT_free(P); EC_POINT_free(Q); EC_POINT_free(R); BN_free(x); BN_free(y); BN_free(z); if (P_160) EC_GROUP_free(P_160); if (P_192) EC_GROUP_free(P_192); if (P_224) EC_GROUP_free(P_224); if (P_256) EC_GROUP_free(P_256); if (P_384) EC_GROUP_free(P_384); if (P_521) EC_GROUP_free(P_521); }
static int gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, unsigned char **method, size_t *method_len, unsigned char **pubkeydata, size_t *pubkeydata_len, EVP_PKEY *pk) { int rc = 0; EC_KEY *ec = NULL; unsigned char *p; unsigned char *method_buf = NULL; unsigned char *key; size_t key_len = 0; unsigned char *octal_value = NULL; size_t octal_len; const EC_POINT *public_key; const EC_GROUP *group; BN_CTX *bn_ctx; libssh2_curve_type type; _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Computing public key from EC private key envelop"); bn_ctx = BN_CTX_new(); if(bn_ctx == NULL) return -1; ec = EVP_PKEY_get1_EC_KEY(pk); if(ec == NULL) { rc = -1; goto clean_exit; } public_key = EC_KEY_get0_public_key(ec); group = EC_KEY_get0_group(ec); type = _libssh2_ecdsa_key_get_curve_type(ec); method_buf = LIBSSH2_ALLOC(session, 19); if(method_buf == NULL) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "out of memory"); } if(type == LIBSSH2_EC_CURVE_NISTP256) memcpy(method_buf, "ecdsa-sha2-nistp256", 19); else if(type == LIBSSH2_EC_CURVE_NISTP384) memcpy(method_buf, "ecdsa-sha2-nistp384", 19); else if(type == LIBSSH2_EC_CURVE_NISTP521) memcpy(method_buf, "ecdsa-sha2-nistp521", 19); else { _libssh2_debug(session, LIBSSH2_TRACE_ERROR, "Unsupported EC private key type"); rc = -1; goto clean_exit; } /* get length */ octal_len = EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, bn_ctx); if(octal_len > EC_MAX_POINT_LEN) { rc = -1; goto clean_exit; } octal_value = malloc(octal_len); if(octal_value == NULL) { rc = -1; goto clean_exit; } /* convert to octal */ if(EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, octal_value, octal_len, bn_ctx) != octal_len) { rc = -1; goto clean_exit; } /* Key form is: type_len(4) + type(19) + domain_len(4) + domain(8) + pub_key_len(4) + pub_key(~65). */ key_len = 4 + 19 + 4 + 8 + 4 + octal_len; key = LIBSSH2_ALLOC(session, key_len); if(key == NULL) { rc = -1; goto clean_exit; } /* Process key encoding. */ p = key; /* Key type */ _libssh2_store_str(&p, (const char *)method_buf, 19); /* Name domain */ _libssh2_store_str(&p, (const char *)method_buf + 11, 8); /* Public key */ _libssh2_store_str(&p, (const char *)octal_value, octal_len); *method = method_buf; *method_len = 19; *pubkeydata = key; *pubkeydata_len = key_len; clean_exit: if(ec != NULL) EC_KEY_free(ec); if(bn_ctx != NULL) { BN_CTX_free(bn_ctx); } if(octal_value != NULL) free(octal_value); if(rc == 0) return 0; if(method_buf != NULL) LIBSSH2_FREE(session, method_buf); return -1; }
int generateRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, data_chunk &sigC, uint8_t *pSigS) { // https://bitcointalk.org/index.php?topic=972541.msg10619684 if (fDebugRingSig) LogPrintf("%s: Ring size %d.\n", __func__, nRingSize); assert(nRingSize < 200); RandAddSeedPerfmon(); memset(pSigS, 0, EC_SECRET_SIZE * nRingSize); int rv = 0; int nBytes; uint256 tmpPkHash; uint256 tmpHash; uint8_t tempData[66]; // hold raw point data to hash ec_secret sAlpha; if (0 != GenerateRandomSecret(sAlpha)) return errorN(1, "%s: GenerateRandomSecret failed.", __func__); CHashWriter ssPkHash(SER_GETHASH, PROTOCOL_VERSION); CHashWriter ssCjHash(SER_GETHASH, PROTOCOL_VERSION); uint256 test; for (int i = 0; i < nRingSize; ++i) { ssPkHash.write((const char*)&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE); if (i == nSecretOffset) continue; int k; // NOTE: necessary to clamp? for (k = 0; k < 32; ++k) { if (1 != RAND_bytes(&pSigS[i * EC_SECRET_SIZE], 32)) return errorN(1, "%s: RAND_bytes ERR_get_error %u.", __func__, ERR_get_error()); memcpy(test.begin(), &pSigS[i * EC_SECRET_SIZE], 32); if (test > MIN_SECRET && test < MAX_SECRET) break; }; if (k > 31) return errorN(1, "%s: Failed to generate a valid key.", __func__); }; tmpPkHash = ssPkHash.GetHash(); BN_CTX_start(bnCtx); BIGNUM *bnT = BN_CTX_get(bnCtx); BIGNUM *bnT2 = BN_CTX_get(bnCtx); BIGNUM *bnS = BN_CTX_get(bnCtx); BIGNUM *bnC = BN_CTX_get(bnCtx); BIGNUM *bnCj = BN_CTX_get(bnCtx); BIGNUM *bnA = BN_CTX_get(bnCtx); EC_POINT *ptKi = NULL; EC_POINT *ptPk = NULL; EC_POINT *ptT1 = NULL; EC_POINT *ptT2 = NULL; EC_POINT *ptT3 = NULL; EC_POINT *ptT4 = NULL; if ( !(ptKi = EC_POINT_new(ecGrp)) || !(ptPk = EC_POINT_new(ecGrp)) || !(ptT1 = EC_POINT_new(ecGrp)) || !(ptT2 = EC_POINT_new(ecGrp)) || !(ptT3 = EC_POINT_new(ecGrp)) || !(ptT4 = EC_POINT_new(ecGrp))) { LogPrintf("%s: EC_POINT_new failed.\n", __func__); rv = 1; goto End; }; // get keyimage as point if (!EC_POINT_oct2point(ecGrp, ptKi, &keyImage[0], EC_COMPRESSED_SIZE, bnCtx)) { LogPrintf("%s: extract ptKi failed.\n", __func__); rv = 1; goto End; }; // c_{j+1} = h(P_1,...,P_n,alpha*G,alpha*H(P_j)) if (!bnA || !(BN_bin2bn(&sAlpha.e[0], EC_SECRET_SIZE, bnA))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; // ptT1 = alpha * G if (!EC_POINT_mul(ecGrp, ptT1, bnA, NULL, NULL, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT3 = H(Pj) if (hashToEC(&pPubkeys[nSecretOffset * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT2, ptT3) != 0) { LogPrintf("%s: hashToEC failed.\n", __func__); rv = 1; goto End; }; ssCjHash.write((const char*)tmpPkHash.begin(), 32); // ptT2 = alpha * H(P_j) // ptT2 = alpha * ptT3 if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnA, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; if ( !(EC_POINT_point2oct(ecGrp, ptT1, POINT_CONVERSION_COMPRESSED, &tempData[0], 33, bnCtx) == (int) EC_COMPRESSED_SIZE) || !(EC_POINT_point2oct(ecGrp, ptT2, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE)) { LogPrintf("%s: extract ptL and ptR failed.\n", __func__); rv = 1; goto End; }; ssCjHash.write((const char*)&tempData[0], 66); tmpHash = ssCjHash.GetHash(); if (!bnC || !(BN_bin2bn(tmpHash.begin(), EC_SECRET_SIZE, bnC)) // bnC lags i by 1 || !BN_mod(bnC, bnC, bnOrder, bnCtx)) { LogPrintf("%s: hash -> bnC failed.\n", __func__); rv = 1; goto End; }; // c_{j+2} = h(P_1,...,P_n,s_{j+1}*G+c_{j+1}*P_{j+1},s_{j+1}*H(P_{j+1})+c_{j+1}*I_j) for (int k = 0, ib = (nSecretOffset + 1) % nRingSize, i = (nSecretOffset + 2) % nRingSize; k < nRingSize; ++k, ib=i, i=(i+1) % nRingSize) { if (k == nRingSize - 1) { // s_j = alpha - c_j*x_j mod n. if (!bnT || !BN_bin2bn(&secret.e[0], EC_SECRET_SIZE, bnT)) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; if (!BN_mul(bnT2, bnCj, bnT, bnCtx)) { LogPrintf("%s: BN_mul failed.\n", __func__); rv = 1; goto End; }; if (!BN_mod_sub(bnS, bnA, bnT2, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_sub failed.\n", __func__); rv = 1; goto End; }; if (!bnS || (nBytes = BN_num_bytes(bnS)) > (int) EC_SECRET_SIZE || BN_bn2bin(bnS, &pSigS[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes) { LogPrintf("%s: bnS -> pSigS failed.\n", __func__); rv = 1; goto End; }; if (nSecretOffset != nRingSize - 1) break; }; if (!bnS || !(BN_bin2bn(&pSigS[ib * EC_SECRET_SIZE], EC_SECRET_SIZE, bnS))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; // bnC is from last round (ib) if (!EC_POINT_oct2point(ecGrp, ptPk, &pPubkeys[ib * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnCtx)) { LogPrintf("%s: EC_POINT_oct2point failed.\n", __func__); rv = 1; goto End; }; // ptT1 = s_{j+1}*G+c_{j+1}*P_{j+1} if (!EC_POINT_mul(ecGrp, ptT1, bnS, ptPk, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; //s_{j+1}*H(P_{j+1})+c_{j+1}*I_j if (hashToEC(&pPubkeys[ib * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT2, ptT2) != 0) { LogPrintf("%s: hashToEC failed.\n", __func__); rv = 1; goto End; }; // ptT3 = s_{j+1}*H(P_{j+1}) if (!EC_POINT_mul(ecGrp, ptT3, NULL, ptT2, bnS, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT4 = c_{j+1}*I_j if (!EC_POINT_mul(ecGrp, ptT4, NULL, ptKi, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT2 = ptT3 + ptT4 if (!EC_POINT_add(ecGrp, ptT2, ptT3, ptT4, bnCtx)) { LogPrintf("%s: EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; if ( !(EC_POINT_point2oct(ecGrp, ptT1, POINT_CONVERSION_COMPRESSED, &tempData[0], 33, bnCtx) == (int) EC_COMPRESSED_SIZE) || !(EC_POINT_point2oct(ecGrp, ptT2, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE)) { LogPrintf("%s: extract ptL and ptR failed.\n", __func__); rv = 1; goto End; }; CHashWriter ssCHash(SER_GETHASH, PROTOCOL_VERSION); ssCHash.write((const char*)tmpPkHash.begin(), 32); ssCHash.write((const char*)&tempData[0], 66); tmpHash = ssCHash.GetHash(); if (!bnC || !(BN_bin2bn(tmpHash.begin(), EC_SECRET_SIZE, bnC)) // bnC lags i by 1 || !BN_mod(bnC, bnC, bnOrder, bnCtx)) { LogPrintf("%s: hash -> bnC failed.\n", __func__); rv = 1; goto End; }; if (i == nSecretOffset && !BN_copy(bnCj, bnC)) { LogPrintf("%s: BN_copy failed.\n", __func__); rv = 1; goto End; }; if (i == 0) { memset(tempData, 0, EC_SECRET_SIZE); if ((nBytes = BN_num_bytes(bnC)) > (int) EC_SECRET_SIZE || BN_bn2bin(bnC, &tempData[0 + (EC_SECRET_SIZE-nBytes)]) != nBytes) { LogPrintf("%s: bnC -> sigC failed.\n", __func__); rv = 1; goto End; }; try { sigC.resize(32); } catch (std::exception& e) { LogPrintf("%s: sigC.resize failed.\n", __func__); rv = 1; goto End; }; memcpy(&sigC[0], tempData, EC_SECRET_SIZE); }; }; End: EC_POINT_free(ptKi); EC_POINT_free(ptPk); EC_POINT_free(ptT1); EC_POINT_free(ptT2); EC_POINT_free(ptT3); EC_POINT_free(ptT4); BN_CTX_end(bnCtx); return rv; };
size_t EC_KEY_public_key_to_oct(const EC_KEY *key, uint8_t *out, size_t out_len) { return EC_POINT_point2oct(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key), out, out_len, NULL); }
static SM9Signature *SM9_do_sign_type1curve(SM9PublicParameters *mpk, const unsigned char *dgst, size_t dgstlen, SM9PrivateKey *sk) { int e = 1; SM9Signature *ret = NULL; BN_CTX *bn_ctx = NULL; EC_GROUP *group = NULL; EC_POINT *point = NULL; BN_GFP2 *w = NULL; unsigned char *buf = NULL; BIGNUM *r; BIGNUM *l; const EVP_MD *md; int point_form = POINT_CONVERSION_UNCOMPRESSED; size_t size; if (!mpk || !dgst || dgstlen <= 0 || !sk) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_PASSED_NULL_PARAMETER); return NULL; } if (dgstlen > EVP_MAX_MD_SIZE) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, SM9_R_INVALID_DIGEST); return NULL; } /* BN_CTX */ if (!(bn_ctx = BN_CTX_new())) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_MALLOC_FAILURE); goto end; } BN_CTX_start(bn_ctx); /* EC_GROUP */ if (!(group = EC_GROUP_new_type1curve_ex(mpk->p, mpk->a, mpk->b, mpk->pointP1->data, mpk->pointP1->length, mpk->order, mpk->cofactor, bn_ctx))) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, SM9_R_INVALID_TYPE1CURVE); goto end; } /* malloc */ ret = SM9Signature_new(); point = EC_POINT_new(group); r = BN_CTX_get(bn_ctx); l = BN_CTX_get(bn_ctx); if (!ret || !point || !r || !l) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_MALLOC_FAILURE); goto end; } /* md = mpk->hashfcn */ if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, SM9_R_INVALID_MD); goto end; } do { /* rand r in [1, mpk->order - 1] */ do { if (!BN_rand_range(r, mpk->order)) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); goto end; } } while (BN_is_zero(r)); /* get w = mpk->g = e(mpk->pointP1, mpk->pointPpub) */ if (!BN_bn2gfp2(mpk->g1, w, mpk->p, bn_ctx)) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); goto end; } /* w = w^r = (mpk->g)^r in F_p^2 */ if (!BN_GFP2_exp(w, w, r, mpk->p, bn_ctx)) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); goto end; } /* prepare w buf and canonical(w, order=0) */ if (!BN_GFP2_canonical(w, NULL, &size, 0, mpk->p, bn_ctx)) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); goto end; } if (!(buf = OPENSSL_malloc(size))) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_MALLOC_FAILURE); goto end; } if (!BN_GFP2_canonical(w, buf, &size, 0, mpk->p, bn_ctx)) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); goto end; } /* ret->h = H2(H(m)||w) in range defined by mpk->order */ if (!SM9_hash2(md, &ret->h, dgst, dgstlen, buf, size, mpk->order, bn_ctx)) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_SM9_LIB); goto end; } /* l = (r - ret->h) (mod mpk->order) */ if (!BN_mod_sub(l, r, ret->h, mpk->order, bn_ctx)) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); goto end; } /* if l == 0, re-generate r */ } while (BN_is_zero(l)); /* point = sk->prointPoint */ if (!EC_POINT_oct2point(group, point, sk->privatePoint->data, sk->privatePoint->length, bn_ctx)) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_EC_LIB); goto end; } /* sig->pointS = sk->privatePoint * l */ if (!EC_POINT_mul(group, point, NULL, point, l, bn_ctx)) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_EC_LIB); goto end; } if (!(size = EC_POINT_point2oct(group, point, point_form, NULL, 0, bn_ctx))) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_EC_LIB); goto end; } if (!ASN1_OCTET_STRING_set(ret->pointS, NULL, size)) { SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_EC_LIB); goto end; } if (!EC_POINT_point2oct(group, point, point_form, ret->pointS->data, ret->pointS->length, bn_ctx)) { goto end; } e = 0; end: if (e && ret) { SM9Signature_free(ret); ret = NULL; } if (bn_ctx) { BN_CTX_end(bn_ctx); } BN_CTX_free(bn_ctx); EC_GROUP_free(group); EC_POINT_free(point); BN_GFP2_free(w); OPENSSL_free(buf); return NULL; }
static int extract_ec_params(CPK_MASTER_SECRET *master, CPK_PUBLIC_PARAMS *param) { int ret = 0; EC_KEY *ec_key = NULL; const EC_GROUP *ec_group; BIGNUM *bn = BN_new(); BIGNUM *order = BN_new(); BN_CTX *ctx = BN_CTX_new(); EC_POINT *pt = NULL; int i, bn_size, pt_size, num_factors; const unsigned char *bn_ptr; unsigned char *pt_ptr; if (!bn || !order || !ctx) { goto err; } if (!(ec_key = X509_ALGOR_get1_EC_KEY(master->pkey_algor))) { goto err; } ec_group = EC_KEY_get0_group(ec_key); if (!(EC_GROUP_get_order(ec_group, order, ctx))) { goto err; } bn_size = BN_num_bytes(order); pt_size = bn_size + 1; if ((num_factors = CPK_MAP_num_factors(master->map_algor)) <= 0) { goto err; } if (M_ASN1_STRING_length(master->secret_factors) != bn_size * num_factors) { goto err; } if (!ASN1_STRING_set(param->public_factors, NULL, pt_size * num_factors)) { goto err; } bn_ptr = M_ASN1_STRING_data(master->secret_factors); pt_ptr = M_ASN1_STRING_data(param->public_factors); memset(pt_ptr, 0, M_ASN1_STRING_length(param->public_factors)); if (!(pt = EC_POINT_new(ec_group))) { goto err; } for (i = 0; i < num_factors; i++) { if (!BN_bin2bn(bn_ptr, bn_size, bn)) { goto err; } if (BN_is_zero(bn) || BN_cmp(bn, order) >= 0) { goto err; } if (!EC_POINT_mul(ec_group, pt, bn, NULL, NULL, ctx)) { goto err; } if (!EC_POINT_point2oct(ec_group, pt, POINT_CONVERSION_COMPRESSED, pt_ptr, pt_size, ctx)) { goto err; } bn_ptr += bn_size; pt_ptr += pt_size; } ret = 1; err: if (ec_key) EC_KEY_free(ec_key); if (bn) BN_free(bn); if (order) BN_free(order); if (ctx) BN_CTX_free(ctx); if (pt) EC_POINT_free(pt); return ret; }
int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, uint8_t *pSigc, uint8_t *pSigr) { if (fDebugRingSig) LogPrintf("%s: Ring size %d.\n", __func__, nRingSize); int rv = 0; int nBytes; BN_CTX_start(bnCtx); BIGNUM *bnKS = BN_CTX_get(bnCtx); BIGNUM *bnK1 = BN_CTX_get(bnCtx); BIGNUM *bnK2 = BN_CTX_get(bnCtx); BIGNUM *bnT = BN_CTX_get(bnCtx); BIGNUM *bnH = BN_CTX_get(bnCtx); BIGNUM *bnSum = BN_CTX_get(bnCtx); EC_POINT *ptT1 = NULL; EC_POINT *ptT2 = NULL; EC_POINT *ptT3 = NULL; EC_POINT *ptPk = NULL; EC_POINT *ptKi = NULL; EC_POINT *ptL = NULL; EC_POINT *ptR = NULL; uint8_t tempData[66]; // hold raw point data to hash uint256 commitHash; ec_secret scData1, scData2; CHashWriter ssCommitHash(SER_GETHASH, PROTOCOL_VERSION); ssCommitHash << txnHash; // zero signature memset(pSigc, 0, EC_SECRET_SIZE * nRingSize); memset(pSigr, 0, EC_SECRET_SIZE * nRingSize); // ks = random 256 bit int mod P if (GenerateRandomSecret(scData1) && (rv = errorN(1, "%s: GenerateRandomSecret failed.", __func__))) goto End; if (!bnKS || !(BN_bin2bn(&scData1.e[0], EC_SECRET_SIZE, bnKS))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; // zero sum if (!bnSum || !(BN_zero(bnSum))) { LogPrintf("%s: BN_zero failed.\n", __func__); rv = 1; goto End; }; if ( !(ptT1 = EC_POINT_new(ecGrp)) || !(ptT2 = EC_POINT_new(ecGrp)) || !(ptT3 = EC_POINT_new(ecGrp)) || !(ptPk = EC_POINT_new(ecGrp)) || !(ptKi = EC_POINT_new(ecGrp)) || !(ptL = EC_POINT_new(ecGrp)) || !(ptR = EC_POINT_new(ecGrp))) { LogPrintf("%s: EC_POINT_new failed.\n", __func__); rv = 1; goto End; }; // get keyimage as point if (!(bnT = BN_bin2bn(&keyImage[0], EC_COMPRESSED_SIZE, bnT)) || !(ptKi) || !(ptKi = EC_POINT_bn2point(ecGrp, bnT, ptKi, bnCtx))) { LogPrintf("%s: extract ptKi failed.\n", __func__); rv = 1; goto End; }; for (int i = 0; i < nRingSize; ++i) { if (i == nSecretOffset) { // k = random 256 bit int mod P // L = k * G // R = k * HashToEC(PKi) if (!EC_POINT_mul(ecGrp, ptL, bnKS, NULL, NULL, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT1) != 0) { LogPrintf("%s: hashToEC failed.\n", __func__); rv = 1; goto End; }; if (!EC_POINT_mul(ecGrp, ptR, NULL, ptT1, bnKS, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; } else { // k1 = random 256 bit int mod P // k2 = random 256 bit int mod P // Li = k1 * Pi + k2 * G // Ri = k1 * I + k2 * Hp(Pi) // ci = k1 // ri = k2 if (GenerateRandomSecret(scData1) != 0 || !bnK1 || !(BN_bin2bn(&scData1.e[0], EC_SECRET_SIZE, bnK1)) || GenerateRandomSecret(scData2) != 0 || !bnK2 || !(BN_bin2bn(&scData2.e[0], EC_SECRET_SIZE, bnK2))) { LogPrintf("%s: k1 and k2 failed.\n", __func__); rv = 1; goto End; }; // get Pk i as point if (!(bnT = BN_bin2bn(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT)) || !(ptPk) || !(ptPk = EC_POINT_bn2point(ecGrp, bnT, ptPk, bnCtx))) { LogPrintf("%s: extract ptPk failed.\n", __func__); rv = 1; goto End; }; // ptT1 = k1 * Pi if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptPk, bnK1, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT2 = k2 * G if (!EC_POINT_mul(ecGrp, ptT2, bnK2, NULL, NULL, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptL = ptT1 + ptT2 if (!EC_POINT_add(ecGrp, ptL, ptT1, ptT2, bnCtx)) { LogPrintf("%s: EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; // ptT3 = Hp(Pi) if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT3) != 0) { LogPrintf("%s: hashToEC failed.\n", __func__); rv = 1; goto End; }; // ptT1 = k1 * I if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnK1, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT2 = k2 * ptT3 if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnK2, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptR = ptT1 + ptT2 if (!EC_POINT_add(ecGrp, ptR, ptT1, ptT2, bnCtx)) { LogPrintf("%s: EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; memcpy(&pSigc[i * EC_SECRET_SIZE], &scData1.e[0], EC_SECRET_SIZE); memcpy(&pSigr[i * EC_SECRET_SIZE], &scData2.e[0], EC_SECRET_SIZE); // sum = (sum + sigc) % N , sigc == bnK1 if (!BN_mod_add(bnSum, bnSum, bnK1, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_add failed.\n", __func__); rv = 1; goto End; }; }; // -- add ptL and ptR to hash if ( !(EC_POINT_point2oct(ecGrp, ptL, POINT_CONVERSION_COMPRESSED, &tempData[0], 33, bnCtx) == (int) EC_COMPRESSED_SIZE) || !(EC_POINT_point2oct(ecGrp, ptR, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE)) { LogPrintf("%s: extract ptL and ptR failed.\n", __func__); rv = 1; goto End; }; ssCommitHash.write((const char*)&tempData[0], 66); }; commitHash = ssCommitHash.GetHash(); if (!(bnH) || !(bnH = BN_bin2bn(commitHash.begin(), EC_SECRET_SIZE, bnH))) { LogPrintf("%s: commitHash -> bnH failed.\n", __func__); rv = 1; goto End; }; if (!BN_mod(bnH, bnH, bnOrder, bnCtx)) // this is necessary { LogPrintf("%s: BN_mod failed.\n", __func__); rv = 1; goto End; }; // sigc[nSecretOffset] = (bnH - bnSum) % N if (!BN_mod_sub(bnT, bnH, bnSum, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_sub failed.\n", __func__); rv = 1; goto End; }; if ((nBytes = BN_num_bytes(bnT)) > (int)EC_SECRET_SIZE || BN_bn2bin(bnT, &pSigc[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes) { LogPrintf("%s: bnT -> pSigc failed.\n", __func__); rv = 1; goto End; }; // sigr[nSecretOffset] = (bnKS - sigc[nSecretOffset] * bnSecret) % N // reuse bnH for bnSecret if (!bnH || !(BN_bin2bn(&secret.e[0], EC_SECRET_SIZE, bnH))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; // bnT = sigc[nSecretOffset] * bnSecret , TODO: mod N ? if (!BN_mul(bnT, bnT, bnH, bnCtx)) { LogPrintf("%s: BN_mul failed.\n", __func__); rv = 1; goto End; }; if (!BN_mod_sub(bnT, bnKS, bnT, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_sub failed.\n", __func__); rv = 1; goto End; }; if ((nBytes = BN_num_bytes(bnT)) > (int) EC_SECRET_SIZE || BN_bn2bin(bnT, &pSigr[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes) { LogPrintf("%s: bnT -> pSigr failed.\n", __func__); rv = 1; goto End; }; End: EC_POINT_free(ptT1); EC_POINT_free(ptT2); EC_POINT_free(ptT3); EC_POINT_free(ptPk); EC_POINT_free(ptKi); EC_POINT_free(ptL); EC_POINT_free(ptR); BN_CTX_end(bnCtx); return rv; };
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){ /* ECDH keys */ ssh_string q_c_string; ssh_string q_s_string; EC_KEY *ecdh_key; const EC_GROUP *group; const EC_POINT *ecdh_pubkey; bignum_CTX ctx; /* SSH host keys (rsa,dsa,ecdsa) */ ssh_key privkey; ssh_string sig_blob = NULL; int len; int rc; /* Extract the client pubkey from the init packet */ q_c_string = ssh_buffer_get_ssh_string(packet); if (q_c_string == NULL) { ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet"); return SSH_ERROR; } session->next_crypto->ecdh_client_pubkey = q_c_string; /* Build server's keypair */ ctx = BN_CTX_new(); ecdh_key = EC_KEY_new_by_curve_name(NISTP256); if (ecdh_key == NULL) { ssh_set_error_oom(session); BN_CTX_free(ctx); return SSH_ERROR; } group = EC_KEY_get0_group(ecdh_key); EC_KEY_generate_key(ecdh_key); ecdh_pubkey = EC_KEY_get0_public_key(ecdh_key); len = EC_POINT_point2oct(group, ecdh_pubkey, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, ctx); q_s_string = ssh_string_new(len); if (q_s_string == NULL) { EC_KEY_free(ecdh_key); BN_CTX_free(ctx); return SSH_ERROR; } EC_POINT_point2oct(group, ecdh_pubkey, POINT_CONVERSION_UNCOMPRESSED, ssh_string_data(q_s_string), len, ctx); BN_CTX_free(ctx); session->next_crypto->ecdh_privkey = ecdh_key; session->next_crypto->ecdh_server_pubkey = q_s_string; /* build k and session_id */ rc = ecdh_build_k(session); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Cannot build k number"); return SSH_ERROR; } /* privkey is not allocated */ rc = ssh_get_key_params(session, &privkey); if (rc == SSH_ERROR) { return SSH_ERROR; } rc = ssh_make_sessionid(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not create a session id"); return SSH_ERROR; } sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey); if (sig_blob == NULL) { ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); return SSH_ERROR; } rc = ssh_buffer_pack(session->out_buffer, "bSSS", SSH2_MSG_KEXDH_REPLY, session->next_crypto->server_pubkey, /* host's pubkey */ q_s_string, /* ecdh public key */ sig_blob); /* signature blob */ ssh_string_free(sig_blob); if (rc != SSH_OK) { ssh_set_error_oom(session); return SSH_ERROR; } SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent"); rc = ssh_packet_send(session); if (rc == SSH_ERROR) { return SSH_ERROR; } /* Send the MSG_NEWKEYS */ rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); if (rc < 0) { return SSH_ERROR;; } session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; rc = ssh_packet_send(session); SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); return rc; }
/* creates a bitcoin address+private key from the SHA256 * hash of string. converts to base58 if base58 is 'true' * returns 1 if successful, 0 if not*/ int create_address_from_string(const unsigned char *string, unsigned char *address, unsigned char *priv_key, EC_GROUP *precompgroup, bool base58, bool debug) { u_int8_t * hash = malloc(SHA256_DIGEST_LENGTH); BIGNUM * n = BN_new(); //first we hash the string SHA256 (string, strlen(string), hash); //then we convert the hash to the BIGNUM n n = BN_bin2bn(hash, SHA256_DIGEST_LENGTH, n); BIGNUM * order = BN_new(); BIGNUM * nmodorder = BN_new(); BN_CTX *bnctx; bnctx = BN_CTX_new(); //then we create a new EC group with the curve secp256k1 EC_GROUP * pgroup; pgroup = EC_GROUP_new_by_curve_name(NID_secp256k1); if (!pgroup) { printf("ERROR: Couldn't get new group\n"); return 0; } //now we need to get the order of the group, and make sure that //the number we use for the private key is less than or equal to //the group order by using "nmodorder = n % order" EC_GROUP_get_order(pgroup, order, NULL); BN_mod(nmodorder, n, order, bnctx); if (BN_is_zero(nmodorder)) { printf("ERROR: SHA256(string) % order == 0. Pick another string.\n"); return 0; } if (debug) printf ("Secret number: %s\n", BN_bn2dec(nmodorder)); //now we create a new EC point, ecpoint, and place in it the secp256k1 //generator point multiplied by nmodorder. this newly created //point is the public key EC_POINT * ecpoint = EC_POINT_new(pgroup); if (!EC_POINT_mul(pgroup, ecpoint, nmodorder, NULL, NULL, NULL)) { printf("ERROR: Couldn't multiply the generator point with n\n"); return 0; } if (debug) { BIGNUM *x=NULL, *y=NULL; x=BN_new(); y=BN_new(); if (!EC_POINT_get_affine_coordinates_GFp(pgroup, ecpoint, x, y, NULL)) { printf("ERROR: Failed getting coordinates."); //don't fail on debug fail //return 0; } printf ("Public key coordinates. x: %s, y: %s\n", BN_bn2dec(x), BN_bn2dec(y)); BN_free(x); BN_free(y); } //then we need to convert the public key point to data //first we get the required size of the buffer in which the data is placed //by passing NULL as the buffer argument to EC_POINT_point2oct unsigned int bufsize = EC_POINT_point2oct (pgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); u_int8_t * buffer = malloc(bufsize); //then we place the data in the buffer int len = EC_POINT_point2oct (pgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, buffer, bufsize, NULL); if (len == 0) { printf("ERROR: Couldn't convert point to octet string."); return 0; } if (debug) { printf("DER encoded public key: "); print_hex(buffer, len); } //next we need to hash the public key data. first with SHA256, then with RIPEMD160 SHA256(buffer, len, hash); if (debug) { printf("SHA256 hash of public key: "); print_hex(hash, SHA256_DIGEST_LENGTH); } u_int8_t * ripemd = malloc(RIPEMD160_DIGEST_LENGTH+1+4); RIPEMD160(hash, SHA256_DIGEST_LENGTH, ripemd); if (debug) { printf("RIPEMD160 hash of SHA256 hash: "); print_hex(ripemd, RIPEMD160_DIGEST_LENGTH); } if (base58 == true) { //here we add the version byte to the beginning of the public key and four checksum //bytes at the end prepare_for_address(ripemd, RIPEMD160_DIGEST_LENGTH, 0); if (debug) { printf("Address in hex with version byte and checksum: "); print_hex(ripemd, RIPEMD160_DIGEST_LENGTH+1+4); } //and we convert the resulting data to base58 base58_encode(ripemd, RIPEMD160_DIGEST_LENGTH+1+4, address); } else { memcpy(address, ripemd, RIPEMD160_DIGEST_LENGTH); } //now we need to convert the big number nmodorder (private key) to data int buflen = BN_num_bytes(nmodorder); u_int8_t * buf = malloc(buflen+1+4); int datalen; //nmodorder is converted to binary representation datalen = BN_bn2bin(nmodorder, buf); if (debug) { printf("Private key: "); print_hex(buf, datalen); } if (base58 == true) { //and we add version byte and four byte checksum to the data prepare_for_address(buf, datalen, 0x80); //and convert this to base58 base58_encode(buf, datalen+5, priv_key); } else { memcpy(priv_key, buf, datalen+5); } free(hash); free(buffer); free(ripemd); free(buf); BN_free(n); BN_free(order); BN_free(nmodorder); if (precompgroup == NULL) EC_GROUP_free(pgroup); EC_POINT_free(ecpoint); BN_CTX_free(bnctx); return 1; }
void * vg_thread_loop(void *arg) { unsigned char hash_buf[128]; unsigned char *eckey_buf; unsigned char hash1[32]; int i, c, len, output_interval; int hash_len; const BN_ULONG rekey_max = 10000000; BN_ULONG npoints, rekey_at, nbatch; vg_context_t *vcp = (vg_context_t *) arg; EC_KEY *pkey = NULL; const EC_GROUP *pgroup; const EC_POINT *pgen; const int ptarraysize = 256; EC_POINT *ppnt[ptarraysize]; EC_POINT *pbatchinc; vg_test_func_t test_func = vcp->vc_test; vg_exec_context_t ctx; vg_exec_context_t *vxcp; struct timeval tvstart; memset(&ctx, 0, sizeof(ctx)); vxcp = &ctx; vg_exec_context_init(vcp, &ctx); pkey = vxcp->vxc_key; pgroup = EC_KEY_get0_group(pkey); pgen = EC_GROUP_get0_generator(pgroup); for (i = 0; i < ptarraysize; i++) { ppnt[i] = EC_POINT_new(pgroup); if (!ppnt[i]) { fprintf(stderr, "ERROR: out of memory?\n"); exit(1); } } pbatchinc = EC_POINT_new(pgroup); if (!pbatchinc) { fprintf(stderr, "ERROR: out of memory?\n"); exit(1); } BN_set_word(&vxcp->vxc_bntmp, ptarraysize); EC_POINT_mul(pgroup, pbatchinc, &vxcp->vxc_bntmp, NULL, NULL, vxcp->vxc_bnctx); EC_POINT_make_affine(pgroup, pbatchinc, vxcp->vxc_bnctx); npoints = 0; rekey_at = 0; nbatch = 0; vxcp->vxc_key = pkey; vxcp->vxc_binres[0] = vcp->vc_addrtype; c = 0; output_interval = 1000; gettimeofday(&tvstart, NULL); if (vcp->vc_format == VCF_SCRIPT) { hash_buf[ 0] = 0x51; // OP_1 hash_buf[ 1] = 0x41; // pubkey length // gap for pubkey hash_buf[67] = 0x51; // OP_1 hash_buf[68] = 0xae; // OP_CHECKMULTISIG eckey_buf = hash_buf + 2; hash_len = 69; } else { eckey_buf = hash_buf; hash_len = 65; } while (!vcp->vc_halt) { if (++npoints >= rekey_at) { vg_exec_context_upgrade_lock(vxcp); /* Generate a new random private key */ EC_KEY_generate_key(pkey); npoints = 0; /* Determine rekey interval */ EC_GROUP_get_order(pgroup, &vxcp->vxc_bntmp, vxcp->vxc_bnctx); BN_sub(&vxcp->vxc_bntmp2, &vxcp->vxc_bntmp, EC_KEY_get0_private_key(pkey)); rekey_at = BN_get_word(&vxcp->vxc_bntmp2); if ((rekey_at == BN_MASK2) || (rekey_at > rekey_max)) rekey_at = rekey_max; assert(rekey_at > 0); EC_POINT_copy(ppnt[0], EC_KEY_get0_public_key(pkey)); vg_exec_context_downgrade_lock(vxcp); npoints++; vxcp->vxc_delta = 0; if (vcp->vc_pubkey_base) EC_POINT_add(pgroup, ppnt[0], ppnt[0], vcp->vc_pubkey_base, vxcp->vxc_bnctx); for (nbatch = 1; (nbatch < ptarraysize) && (npoints < rekey_at); nbatch++, npoints++) { EC_POINT_add(pgroup, ppnt[nbatch], ppnt[nbatch-1], pgen, vxcp->vxc_bnctx); } } else { /* * Common case * * EC_POINT_add() can skip a few multiplies if * one or both inputs are affine (Z_is_one). * This is the case for every point in ppnt, as * well as pbatchinc. */ assert(nbatch == ptarraysize); for (nbatch = 0; (nbatch < ptarraysize) && (npoints < rekey_at); nbatch++, npoints++) { EC_POINT_add(pgroup, ppnt[nbatch], ppnt[nbatch], pbatchinc, vxcp->vxc_bnctx); } } /* * The single most expensive operation performed in this * loop is modular inversion of ppnt->Z. There is an * algorithm implemented in OpenSSL to do batched inversion * that only does one actual BN_mod_inverse(), and saves * a _lot_ of time. * * To take advantage of this, we batch up a few points, * and feed them to EC_POINTs_make_affine() below. */ EC_POINTs_make_affine(pgroup, nbatch, ppnt, vxcp->vxc_bnctx); for (i = 0; i < nbatch; i++, vxcp->vxc_delta++) { /* Hash the public key */ len = EC_POINT_point2oct(pgroup, ppnt[i], POINT_CONVERSION_UNCOMPRESSED, eckey_buf, 65, vxcp->vxc_bnctx); assert(len == 65); SHA256(hash_buf, hash_len, hash1); RIPEMD160(hash1, sizeof(hash1), &vxcp->vxc_binres[1]); switch (test_func(vxcp)) { case 1: npoints = 0; rekey_at = 0; i = nbatch; break; case 2: goto out; default: break; } } c += i; if (c >= output_interval) { output_interval = vg_output_timing(vcp, c, &tvstart); if (output_interval > 250000) output_interval = 250000; c = 0; } vg_exec_context_yield(vxcp); } out: vg_exec_context_del(&ctx); vg_context_thread_exit(vcp); for (i = 0; i < ptarraysize; i++) if (ppnt[i]) EC_POINT_free(ppnt[i]); if (pbatchinc) EC_POINT_free(pbatchinc); return NULL; }
jbyteArray Java_ru_ivanovpv_gorets_psm_nativelib_NativeLib_getECSharedKey( JNIEnv* env, jobject thiz, jbyteArray privKey, jbyteArray pubKey, jint ecGroup) { EC_GROUP * ec_group = NULL; EC_POINT * ec_pub = NULL; EC_POINT * ec_res = NULL; BN_CTX * bn_ctx = NULL; BIGNUM * bn_priv = NULL; jbyte * privKeyArr = NULL; jbyte * pubKeyArr = NULL; jbyteArray resKey = NULL; jbyte resKeyArr[MAX_EC_KEY_SIZE]; jint privKeySize = 0; jint pubKeySize = 0; size_t resKeySize = 0; if ( ((ecGroup != 1) && (ecGroup != 2) && (ecGroup != 3)) || (privKey == NULL) || (pubKey == NULL) ) { goto cleanup; } privKeySize = (*env)->GetArrayLength(env, privKey); pubKeySize = (*env)->GetArrayLength(env, pubKey); if ( (privKeySize <= 0) || (pubKeySize <= 0) ) { goto cleanup; } switch(ecGroup) { case 1: if ( ( privKeySize < (112/8) ) || ( pubKeySize < (112/8+1) ) ) goto cleanup; ec_group = EC_GROUP_new_by_curve_name(NID_secp112r1); break; case 2: if ( ( privKeySize < (256/8) ) || ( pubKeySize < (256/8+1) ) ) goto cleanup; ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1); break; case 3: if ( ( privKeySize < (384/8) ) || ( pubKeySize < (384/8+1) ) ) goto cleanup; ec_group = EC_GROUP_new_by_curve_name(NID_secp384r1); break; default: goto cleanup; } if (!ec_group) { goto cleanup; } if( (bn_priv = BN_new()) == NULL) { goto cleanup; } if( (privKeyArr = (*env)->GetByteArrayElements(env, privKey, NULL)) == NULL ) { goto cleanup; } if ( BN_bin2bn((const unsigned char *)privKeyArr, (int) privKeySize, bn_priv) == NULL ) { goto cleanup; } if ( (bn_ctx = BN_CTX_new()) == NULL ) { goto cleanup; } if ( (ec_pub = EC_POINT_new(ec_group)) == NULL) { goto cleanup; } if( (pubKeyArr = (*env)->GetByteArrayElements(env, pubKey, NULL)) == NULL ) { goto cleanup; } if ( EC_POINT_oct2point((const EC_GROUP *) ec_group, (EC_POINT *) ec_pub, (unsigned char *) pubKeyArr, (size_t) pubKeySize, bn_ctx) == 0 ) { goto cleanup; } if ( (ec_res = EC_POINT_new(ec_group)) == NULL) { goto cleanup; } if (!EC_POINT_mul((const EC_GROUP *) ec_group, ec_res, (const BIGNUM *)NULL, ec_pub, bn_priv, bn_ctx)) { goto cleanup; } if ( (resKeySize = EC_POINT_point2oct((const EC_GROUP *) ec_group, (const EC_POINT *) ec_res, POINT_CONVERSION_COMPRESSED, (unsigned char *) resKeyArr, (size_t) MAX_EC_KEY_SIZE, bn_ctx)) == 0 ) { goto cleanup; } resKey = (*env)->NewByteArray(env, resKeySize); if (resKey == NULL) { goto cleanup; } (*env)->SetByteArrayRegion(env, resKey, 0, resKeySize, (const jbyte*)resKeyArr); memset (resKeyArr, 0, resKeySize); cleanup: if ( ec_group ) EC_GROUP_clear_free( ec_group ); if ( ec_pub ) EC_POINT_clear_free( ec_pub ); if ( ec_res ) EC_POINT_clear_free( ec_res ); if ( bn_priv ) BN_clear_free( bn_priv ); if ( privKeyArr ) (*env)->ReleaseByteArrayElements(env, privKey, privKeyArr, JNI_ABORT); if ( pubKeyArr ) (*env)->ReleaseByteArrayElements(env, pubKey, pubKeyArr, JNI_ABORT); return resKey; }
int SM2_do_decrypt(const EVP_MD *kdf_md, const EVP_MD *mac_md, const SM2_CIPHERTEXT_VALUE *cv, unsigned char *out, size_t *outlen, EC_KEY *ec_key) { int ret = 0; const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key); const BIGNUM *pri_key = EC_KEY_get0_private_key(ec_key); KDF_FUNC kdf = KDF_get_x9_63(kdf_md); EC_POINT *point = NULL; BIGNUM *n = NULL; BIGNUM *h = NULL; BN_CTX *bn_ctx = NULL; EVP_MD_CTX *md_ctx = NULL; unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1]; unsigned char mac[EVP_MAX_MD_SIZE]; unsigned int maclen; int nbytes; size_t size; int i; OPENSSL_assert(kdf_md && mac_md && cv && ec_key); OPENSSL_assert(cv->ephem_point && cv->ciphertext); if (!ec_group || !pri_key) { goto end; } if (!kdf) { goto end; } if (!out) { *outlen = cv->ciphertext_size; return 1; } if (*outlen < cv->ciphertext_size) { goto end; } /* init vars */ point = EC_POINT_new(ec_group); n = BN_new(); h = BN_new(); bn_ctx = BN_CTX_new(); md_ctx = EVP_MD_CTX_create(); if (!point || !n || !h || !bn_ctx || !md_ctx) { goto end; } /* init ec domain parameters */ if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) { goto end; } if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) { goto end; } nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8; OPENSSL_assert(nbytes == BN_num_bytes(n)); #if 0 /* check sm2 curve and md is 256 bits */ OPENSSL_assert(nbytes == 32); OPENSSL_assert(EVP_MD_size(kdf_md) == 32); OPENSSL_assert(EVP_MD_size(mac_md) == 32); #endif /* B2: check [h]C1 != O */ if (!EC_POINT_mul(ec_group, point, NULL, cv->ephem_point, h, bn_ctx)) { goto end; } if (EC_POINT_is_at_infinity(ec_group, point)) { goto end; } /* B3: compute ECDH [d]C1 = (x2, y2) */ if (!EC_POINT_mul(ec_group, point, NULL, cv->ephem_point, pri_key, bn_ctx)) { goto end; } if (!(size = EC_POINT_point2oct(ec_group, point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { goto end; } OPENSSL_assert(size == 1 + nbytes * 2); /* B4: compute t = KDF(x2 || y2, clen) */ *outlen = cv->ciphertext_size; //FIXME: duplicated code kdf(buf + 1, size - 1, out, outlen); /* B5: compute M = C2 xor t */ for (i = 0; i < cv->ciphertext_size; i++) { out[i] ^= cv->ciphertext[i]; } *outlen = cv->ciphertext_size; /* B6: check Hash(x2 || M || y2) == C3 */ if (!EVP_DigestInit_ex(md_ctx, mac_md, NULL)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) { goto end; } if (!EVP_DigestUpdate(md_ctx, out, *outlen)) { goto end; } if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) { goto end; } if (!EVP_DigestFinal_ex(md_ctx, mac, &maclen)) { goto end; } if (cv->mactag_size != maclen || memcmp(cv->mactag, mac, maclen)) { goto end; } ret = 1; end: if (point) EC_POINT_free(point); if (n) BN_free(n); if (h) BN_free(h); if (bn_ctx) BN_CTX_free(bn_ctx); if (md_ctx) EVP_MD_CTX_destroy(md_ctx); return ret; }
ECPV1_KeyPair *keypair = (ECPV1_KeyPair*)obj; ret = EC_KEY_generate_key(keypair->eckey); if (ret == 0) { ret = -1; goto final; } const EC_GROUP *grp = EC_KEY_get0_group(keypair->eckey); keypair->group = grp; EC_GROUP_get_order(grp, keypair->group_order, bnctx); keypair->sk = EC_KEY_get0_private_key(keypair->eckey); keypair->PK = EC_KEY_get0_public_key(keypair->eckey); keypair->bytelen_go = BN_num_bytes(keypair->group_order); keypair->bytelen_point = EC_POINT_point2oct( grp, keypair->PK, POINT_CONVERSION_COMPRESSED, NULL, 0, bnctx); ret = 0; final: return ret; } const char *ECPV1_get_name() { return "ECPV-aes256cbc"; } void *ECPV1_signsess_new(void *keyobj, int bitlen_clr, int bitlen_rec, int bitlen_red) {