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 }
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 }