static cjose_jwk_t *_cjose_jwk_import_RSA(json_t *jwk_json, cjose_err *err) { cjose_jwk_t *jwk = NULL; uint8_t *n_buffer = NULL; uint8_t *e_buffer = NULL; uint8_t *d_buffer = NULL; uint8_t *p_buffer = NULL; uint8_t *q_buffer = NULL; uint8_t *dp_buffer = NULL; uint8_t *dq_buffer = NULL; uint8_t *qi_buffer = NULL; // get the decoded value of n (buflen = 0 means no particular expected len) size_t n_buflen = 0; if (!_decode_json_object_base64url_attribute( jwk_json, CJOSE_JWK_N_STR, &n_buffer, &n_buflen, err)) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_RSA_cleanup; } // get the decoded value of e size_t e_buflen = 0; if (!_decode_json_object_base64url_attribute( jwk_json, CJOSE_JWK_E_STR, &e_buffer, &e_buflen, err)) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_RSA_cleanup; } // get the decoded value of d size_t d_buflen = 0; if (!_decode_json_object_base64url_attribute( jwk_json, CJOSE_JWK_D_STR, &d_buffer, &d_buflen, err)) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_RSA_cleanup; } // get the decoded value of p size_t p_buflen = 0; if (!_decode_json_object_base64url_attribute( jwk_json, CJOSE_JWK_P_STR, &p_buffer, &p_buflen, err)) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_RSA_cleanup; } // get the decoded value of q size_t q_buflen = 0; if (!_decode_json_object_base64url_attribute( jwk_json, CJOSE_JWK_Q_STR, &q_buffer, &q_buflen, err)) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_RSA_cleanup; } // get the decoded value of dp size_t dp_buflen = 0; if (!_decode_json_object_base64url_attribute( jwk_json, CJOSE_JWK_DP_STR, &dp_buffer, &dp_buflen, err)) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_RSA_cleanup; } // get the decoded value of dq size_t dq_buflen = 0; if (!_decode_json_object_base64url_attribute( jwk_json, CJOSE_JWK_DQ_STR, &dq_buffer, &dq_buflen, err)) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_RSA_cleanup; } // get the decoded value of qi size_t qi_buflen = 0; if (!_decode_json_object_base64url_attribute( jwk_json, CJOSE_JWK_QI_STR, &qi_buffer, &qi_buflen, err)) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_RSA_cleanup; } // create an rsa keyspec cjose_jwk_rsa_keyspec rsa_keyspec; memset(&rsa_keyspec, 0, sizeof(cjose_jwk_rsa_keyspec)); rsa_keyspec.n = n_buffer; rsa_keyspec.nlen = n_buflen; rsa_keyspec.e = e_buffer; rsa_keyspec.elen = e_buflen; rsa_keyspec.d = d_buffer; rsa_keyspec.dlen = d_buflen; rsa_keyspec.p = p_buffer; rsa_keyspec.plen = p_buflen; rsa_keyspec.q = q_buffer; rsa_keyspec.qlen = q_buflen; rsa_keyspec.dp = dp_buffer; rsa_keyspec.dplen = dp_buflen; rsa_keyspec.dq = dq_buffer; rsa_keyspec.dqlen = dq_buflen; rsa_keyspec.qi = qi_buffer; rsa_keyspec.qilen = qi_buflen; // create the jwk jwk = cjose_jwk_create_RSA_spec(&rsa_keyspec, err); import_RSA_cleanup: cjose_get_dealloc()(n_buffer); cjose_get_dealloc()(e_buffer); cjose_get_dealloc()(d_buffer); cjose_get_dealloc()(p_buffer); cjose_get_dealloc()(q_buffer); cjose_get_dealloc()(dp_buffer); cjose_get_dealloc()(dq_buffer); cjose_get_dealloc()(qi_buffer); return jwk; }
/* * convert the RSA public key in the X.509 certificate in the BIO pointed to * by "input" to a JSON Web Key object */ static apr_byte_t oidc_jwk_rsa_bio_to_jwk(apr_pool_t *pool, BIO *input, cjose_jwk_t **jwk, int is_private_key, oidc_jose_error_t *err) { X509 *x509 = NULL; EVP_PKEY *pkey = NULL; apr_byte_t rv = FALSE; cjose_jwk_rsa_keyspec key_spec; memset(&key_spec, 0, sizeof(cjose_jwk_rsa_keyspec)); if (is_private_key) { /* get the private key struct from the BIO */ if ((pkey = PEM_read_bio_PrivateKey(input, NULL, NULL, NULL)) == NULL) { oidc_jose_error_openssl(err, "PEM_read_bio_PrivateKey"); goto end; } } else { /* read the X.509 struct */ if ((x509 = PEM_read_bio_X509_AUX(input, NULL, NULL, NULL)) == NULL) { oidc_jose_error_openssl(err, "PEM_read_bio_X509_AUX"); goto end; } /* get the public key struct from the X.509 struct */ if ((pkey = X509_get_pubkey(x509)) == NULL) { oidc_jose_error_openssl(err, "X509_get_pubkey"); goto end; } } /* get the RSA key from the public key struct */ RSA *rsa = EVP_PKEY_get1_RSA(pkey); if (rsa == NULL) { oidc_jose_error_openssl(err, "EVP_PKEY_get1_RSA"); goto end; } const BIGNUM *rsa_n, *rsa_e, *rsa_d; #if OPENSSL_VERSION_NUMBER >= 0x10100005L && !defined (LIBRESSL_VERSION_NUMBER) RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d); #else rsa_n = rsa->n; rsa_e = rsa->e; rsa_d = rsa->d; #endif RSA_free(rsa); /* convert the modulus bignum in to a key/len */ key_spec.nlen = BN_num_bytes(rsa_n); key_spec.n = apr_pcalloc(pool, key_spec.nlen); BN_bn2bin(rsa_n, key_spec.n); /* convert the exponent bignum in to a key/len */ key_spec.elen = BN_num_bytes(rsa_e); key_spec.e = apr_pcalloc(pool, key_spec.elen); BN_bn2bin(rsa_e, key_spec.e); /* convert the private exponent bignum in to a key/len */ if (rsa_d != NULL) { key_spec.dlen = BN_num_bytes(rsa_d); key_spec.d = apr_pcalloc(pool, key_spec.dlen); BN_bn2bin(rsa_d, key_spec.d); } cjose_err cjose_err; *jwk = cjose_jwk_create_RSA_spec(&key_spec, &cjose_err); if (*jwk == NULL) { oidc_jose_error(err, "cjose_jwk_create_RSA_spec failed: %s", oidc_cjose_e2s(pool, cjose_err)); goto end; } char *fingerprint = apr_pcalloc(pool, key_spec.nlen + key_spec.elen); memcpy(fingerprint, key_spec.n, key_spec.nlen); memcpy(fingerprint + key_spec.nlen, key_spec.e, key_spec.elen); if (oidc_jwk_set_or_generate_kid(pool, *jwk, NULL, fingerprint, key_spec.nlen + key_spec.elen, err) == FALSE) { goto end; } rv = TRUE; end: if (pkey) EVP_PKEY_free(pkey); if (x509) X509_free(x509); return rv; }