static int x25519_keygen(EC_KEY *eckey) { unsigned char *key; if (x25519_init_private(eckey, NULL) == 0) return 0; key = eckey->custom_data; if (RAND_bytes(key, EC_X25519_KEYLEN) <= 0) return 0; key[0] &= 248; key[31] &= 127; key[31] |= 64; /* * Although the private key is kept as an array in eckey->custom_data * Set eckey->priv_key too so existing code which uses * EC_KEY_get0_private_key() still works. */ if (eckey->priv_key == NULL) eckey->priv_key = BN_secure_new(); if (eckey->priv_key == NULL) return 0; if (BN_lebin2bn(eckey->custom_data, EC_X25519_KEYLEN, eckey->priv_key) == NULL) return 0; if (eckey->pub_key == NULL) eckey->pub_key = EC_POINT_new(eckey->group); if (eckey->pub_key == NULL) return 0; return x25519_keygenpub(eckey); }
static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r) { *r = BN_lebin2bn(*in, nbyte, NULL); if (*r == NULL) return 0; *in += nbyte; return 1; }
static int x25519_oct2priv(EC_KEY *eckey, unsigned char *buf, size_t len) { if (len != EC_X25519_KEYLEN) return 0; if (x25519_init_private(eckey, buf) == 0) return 0; /* * Although the private key is kept as an array in eckey->custom_data * Set eckey->priv_key too so existing code which uses * EC_KEY_get0_private_key() still works. */ if (eckey->priv_key == NULL) eckey->priv_key = BN_secure_new(); if (eckey->priv_key == NULL) return 0; if (BN_lebin2bn(buf, EC_X25519_KEYLEN, eckey->priv_key) == NULL) return 0; return 1; }
static int test_param_construct(void) { static const char *int_names[] = { "int", "long", "int32", "int64" }; static const char *uint_names[] = { "uint", "ulong", "uint32", "uint64", "size_t" }; static const unsigned char bn_val[16] = { 0xac, 0x75, 0x22, 0x7d, 0x81, 0x06, 0x7a, 0x23, 0xa6, 0xed, 0x87, 0xc7, 0xab, 0xf4, 0x73, 0x22 }; OSSL_PARAM params[20]; char buf[100], buf2[100], *bufp, *bufp2; unsigned char ubuf[100]; void *vp, *vpn = NULL, *vp2; OSSL_PARAM *p; const OSSL_PARAM *cp; static const OSSL_PARAM pend = OSSL_PARAM_END; int i, n = 0, ret = 0; unsigned int u; long int l; unsigned long int ul; int32_t i32; uint32_t u32; int64_t i64; uint64_t u64; size_t j, k, s, sz; double d, d2; BIGNUM *bn = NULL, *bn2 = NULL; params[n++] = OSSL_PARAM_construct_int("int", &i, &sz); params[n++] = OSSL_PARAM_construct_uint("uint", &u, &sz); params[n++] = OSSL_PARAM_construct_long("long", &l, &sz); params[n++] = OSSL_PARAM_construct_ulong("ulong", &ul, &sz); params[n++] = OSSL_PARAM_construct_int32("int32", &i32, &sz); params[n++] = OSSL_PARAM_construct_int64("int64", &i64, &sz); params[n++] = OSSL_PARAM_construct_uint32("uint32", &u32, &sz); params[n++] = OSSL_PARAM_construct_uint64("uint64", &u64, &sz); params[n++] = OSSL_PARAM_construct_size_t("size_t", &s, &sz); params[n++] = OSSL_PARAM_construct_double("double", &d, &sz); params[n++] = OSSL_PARAM_construct_BN("bignum", ubuf, sizeof(ubuf), &sz); params[n++] = OSSL_PARAM_construct_utf8_string("utf8str", buf, sizeof(buf), &sz); params[n++] = OSSL_PARAM_construct_octet_string("octstr", buf, sizeof(buf), &sz); params[n++] = OSSL_PARAM_construct_utf8_ptr("utf8ptr", &bufp, &sz); params[n++] = OSSL_PARAM_construct_octet_ptr("octptr", &vp, &sz); params[n] = pend; /* Search failure */ if (!TEST_ptr_null(OSSL_PARAM_locate(params, "fnord"))) goto err; /* All signed integral types */ for (j = 0; j < OSSL_NELEM(int_names); j++) { if (!TEST_ptr(cp = OSSL_PARAM_locate(params, int_names[j])) || !TEST_true(OSSL_PARAM_set_int32(cp, (int32_t)(3 + j))) || !TEST_true(OSSL_PARAM_get_int64(cp, &i64)) || !TEST_size_t_eq(cp->data_size, sz) || !TEST_size_t_eq((size_t)i64, 3 + j)) { TEST_note("iteration %zu var %s", j + 1, int_names[j]); goto err; } } /* All unsigned integral types */ for (j = 0; j < OSSL_NELEM(uint_names); j++) { if (!TEST_ptr(cp = OSSL_PARAM_locate(params, uint_names[j])) || !TEST_true(OSSL_PARAM_set_uint32(cp, (uint32_t)(3 + j))) || !TEST_true(OSSL_PARAM_get_uint64(cp, &u64)) || !TEST_size_t_eq(cp->data_size, sz) || !TEST_size_t_eq((size_t)u64, 3 + j)) { TEST_note("iteration %zu var %s", j + 1, uint_names[j]); goto err; } } /* Real */ if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "double")) || !TEST_true(OSSL_PARAM_set_double(cp, 3.14)) || !TEST_true(OSSL_PARAM_get_double(cp, &d2)) || !TEST_size_t_eq(sz, sizeof(double)) || !TEST_double_eq(d, d2)) goto err; /* UTF8 string */ bufp = NULL; if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "utf8str")) || !TEST_true(OSSL_PARAM_set_utf8_string(cp, "abcdef")) || !TEST_size_t_eq(sz, sizeof("abcdef")) || !TEST_true(OSSL_PARAM_get_utf8_string(cp, &bufp, 0)) || !TEST_str_eq(bufp, "abcdef")) goto err; OPENSSL_free(bufp); bufp = buf2; if (!TEST_true(OSSL_PARAM_get_utf8_string(cp, &bufp, sizeof(buf2))) || !TEST_str_eq(buf2, "abcdef")) goto err; /* UTF8 pointer */ bufp = buf; sz = 0; if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "utf8ptr")) || !TEST_true(OSSL_PARAM_set_utf8_ptr(cp, "tuvwxyz")) || !TEST_size_t_eq(sz, sizeof("tuvwxyz")) || !TEST_str_eq(bufp, "tuvwxyz") || !TEST_true(OSSL_PARAM_get_utf8_ptr(cp, (const char **)&bufp2)) || !TEST_ptr_eq(bufp2, bufp)) goto err; /* OCTET string */ if (!TEST_ptr(p = locate(params, "octstr")) || !TEST_true(OSSL_PARAM_set_octet_string(p, "abcdefghi", sizeof("abcdefghi"))) || !TEST_size_t_eq(sz, sizeof("abcdefghi"))) goto err; /* Match the return size to avoid trailing garbage bytes */ p->data_size = *p->return_size; if (!TEST_true(OSSL_PARAM_get_octet_string(p, &vpn, 0, &s)) || !TEST_size_t_eq(s, sizeof("abcdefghi")) || !TEST_mem_eq(vpn, sizeof("abcdefghi"), "abcdefghi", sizeof("abcdefghi"))) goto err; vp = buf2; if (!TEST_true(OSSL_PARAM_get_octet_string(p, &vp, sizeof(buf2), &s)) || !TEST_size_t_eq(s, sizeof("abcdefghi")) || !TEST_mem_eq(vp, sizeof("abcdefghi"), "abcdefghi", sizeof("abcdefghi"))) goto err; /* OCTET pointer */ vp = &l; sz = 0; if (!TEST_ptr(p = locate(params, "octptr")) || !TEST_true(OSSL_PARAM_set_octet_ptr(p, &ul, sizeof(ul))) || !TEST_size_t_eq(sz, sizeof(ul)) || !TEST_ptr_eq(vp, &ul)) goto err; /* Match the return size to avoid trailing garbage bytes */ p->data_size = *p->return_size; if (!TEST_true(OSSL_PARAM_get_octet_ptr(p, (const void **)&vp2, &k)) || !TEST_size_t_eq(k, sizeof(ul)) || !TEST_ptr_eq(vp2, vp)) goto err; /* BIGNUM */ if (!TEST_ptr(p = locate(params, "bignum")) || !TEST_ptr(bn = BN_lebin2bn(bn_val, (int)sizeof(bn_val), NULL)) || !TEST_true(OSSL_PARAM_set_BN(p, bn)) || !TEST_size_t_eq(sz, sizeof(bn_val))) goto err; /* Match the return size to avoid trailing garbage bytes */ p->data_size = *p->return_size; if(!TEST_true(OSSL_PARAM_get_BN(p, &bn2)) || !TEST_BN_eq(bn, bn2)) goto err; ret = 1; err: OPENSSL_free(vpn); BN_free(bn); BN_free(bn2); return ret; }
sgx_status_t sgx_rsa3072_sign(const uint8_t * p_data, uint32_t data_size, const sgx_rsa3072_key_t * p_key, sgx_rsa3072_signature_t * p_signature) { if ((p_data == NULL) || (data_size < 1) || (p_key == NULL) || (p_signature == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } sgx_status_t retval = SGX_ERROR_UNEXPECTED; RSA *priv_rsa_key = NULL; EVP_PKEY* priv_pkey = NULL; BIGNUM *n = NULL; BIGNUM *d = NULL; BIGNUM *e = NULL; EVP_MD_CTX* ctx = NULL; const EVP_MD* sha256_md = NULL; size_t siglen = SGX_RSA3072_KEY_SIZE; int ret = 0; CLEAR_OPENSSL_ERROR_QUEUE; do { // converts the modulus value of rsa key, represented as positive integer in little-endian into a BIGNUM // n = BN_lebin2bn((const unsigned char *)p_key->mod, sizeof(p_key->mod), 0); if (n == NULL) { break; } // converts the private exp value of rsa key, represented as positive integer in little-endian into a BIGNUM // d = BN_lebin2bn((const unsigned char *)p_key->d, sizeof(p_key->d), 0); if (d == NULL) { break; } // converts the public exp value of rsa key, represented as positive integer in little-endian into a BIGNUM // e = BN_lebin2bn((const unsigned char *)p_key->e, sizeof(p_key->e), 0); if (e == NULL) { break; } // allocates and initializes an RSA key structure // priv_rsa_key = RSA_new(); if (priv_rsa_key == NULL) { retval = SGX_ERROR_OUT_OF_MEMORY; break; } // sets the modulus, private exp and public exp values of the RSA key // if (RSA_set0_key(priv_rsa_key, n, e, d) != 1) { BN_clear_free(n); BN_clear_free(d); BN_clear_free(e); break; } // allocates an empty EVP_PKEY structure // priv_pkey = EVP_PKEY_new(); if (priv_pkey == NULL) { retval = SGX_ERROR_OUT_OF_MEMORY; break; } // set the referenced key to pub_rsa_key, however these use the supplied key internally and so key will be freed when the parent pkey is freed // if (EVP_PKEY_assign_RSA(priv_pkey, priv_rsa_key) != 1) { RSA_free(priv_rsa_key); break; } // allocates, initializes and returns a digest context // ctx = EVP_MD_CTX_new(); if (NULL == ctx) { retval = SGX_ERROR_OUT_OF_MEMORY; break; } // return EVP_MD structures for SHA256 digest algorithm */ // sha256_md = EVP_sha256(); if (sha256_md == NULL) { break; } // sets up signing context ctx to use digest type // if (EVP_DigestSignInit(ctx, NULL, sha256_md, NULL, priv_pkey) <= 0) { break; } // hashes data_size bytes of data at p_data into the signature context ctx // if (EVP_DigestSignUpdate(ctx, (const void *)p_data, data_size) <= 0) { break; } // signs the data in ctx places the signature in p_signature. // ret = EVP_DigestSignFinal(ctx, (unsigned char *)p_signature, &siglen);//fails if (ret <= 0) { break; } // validates the signature size // if (SGX_RSA3072_KEY_SIZE != siglen) { break; } retval = SGX_SUCCESS; } while (0); if (retval != SGX_SUCCESS) { GET_LAST_OPENSSL_ERROR; } if (ctx) EVP_MD_CTX_free(ctx); if (priv_pkey) { EVP_PKEY_free(priv_pkey); priv_rsa_key = NULL; n = NULL; d = NULL; e = NULL; } if (priv_rsa_key) { RSA_free(priv_rsa_key); n = NULL; d = NULL; e = NULL; } if (n) BN_clear_free(n); if (d) BN_clear_free(d); if (e) BN_clear_free(e); return retval; }
sgx_status_t sgx_rsa3072_verify(const uint8_t *p_data, uint32_t data_size, const sgx_rsa3072_public_key_t *p_public, const sgx_rsa3072_signature_t *p_signature, sgx_rsa_result_t *p_result) { if ((p_data == NULL) || (data_size < 1) || (p_public == NULL) || (p_signature == NULL) || (p_result == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } *p_result = SGX_RSA_INVALID_SIGNATURE; sgx_status_t retval = SGX_ERROR_UNEXPECTED; int verified = 0; RSA *pub_rsa_key = NULL; EVP_PKEY *pub_pkey = NULL; BIGNUM *n = NULL; BIGNUM *e = NULL; const EVP_MD* sha256_md = NULL; EVP_MD_CTX *ctx = NULL; CLEAR_OPENSSL_ERROR_QUEUE; do { // converts the modulus value of rsa key, represented as positive integer in little-endian into a BIGNUM // n = BN_lebin2bn((const unsigned char *)p_public->mod, sizeof(p_public->mod), 0); if (n == NULL) { break; } // converts the public exp value of rsa key, represented as positive integer in little-endian into a BIGNUM // e = BN_lebin2bn((const unsigned char *)p_public->exp, sizeof(p_public->exp), 0); if (e == NULL) { break; } // allocates and initializes an RSA key structure // pub_rsa_key = RSA_new(); if (pub_rsa_key == NULL) { retval = SGX_ERROR_OUT_OF_MEMORY; break; } // sets the modulus and public exp values of the RSA key // if (RSA_set0_key(pub_rsa_key, n, e, NULL) != 1) { BN_clear_free(n); BN_clear_free(e); break; } // allocates an empty EVP_PKEY structure // pub_pkey = EVP_PKEY_new(); if (pub_pkey == NULL) { retval = SGX_ERROR_OUT_OF_MEMORY; break; } // set the referenced key to pub_rsa_key, however these use the supplied key internally and so key will be freed when the parent pkey is freed // if (EVP_PKEY_assign_RSA(pub_pkey, pub_rsa_key) != 1) { RSA_free(pub_rsa_key); break; } // allocates, initializes and returns a digest context // ctx = EVP_MD_CTX_new(); if (ctx == NULL) { retval = SGX_ERROR_OUT_OF_MEMORY; break; } // return EVP_MD structures for SHA256 digest algorithm */ // sha256_md = EVP_sha256(); if (sha256_md == NULL) { break; } // sets up verification context ctx to use digest type // if (EVP_DigestVerifyInit(ctx, NULL, sha256_md, NULL, pub_pkey) <= 0) { break; } // hashes data_size bytes of data at p_data into the verification context ctx. // this function can be called several times on the same ctx to hash additional data // if (EVP_DigestVerifyUpdate(ctx, (const void *)p_data, data_size) <= 0) { break; } // verifies the data in ctx against the signature in p_signature of length SGX_RSA3072_KEY_SIZE // verified = EVP_DigestVerifyFinal(ctx, (const unsigned char *)p_signature, SGX_RSA3072_KEY_SIZE); if (verified) { *p_result = SGX_RSA_VALID; } else if (verified != 0) { break; } retval = SGX_SUCCESS; } while (0); if (retval != SGX_SUCCESS) { GET_LAST_OPENSSL_ERROR; } if (ctx) EVP_MD_CTX_free(ctx); if (pub_pkey) { EVP_PKEY_free(pub_pkey); pub_rsa_key = NULL; n = NULL; e = NULL; } if (pub_rsa_key) { RSA_free(pub_rsa_key); n = NULL; e = NULL; } if (n) BN_clear_free(n); if (e) BN_clear_free(e); return retval; }