static apr_byte_t apr_jwk_parse_rsa_key(apr_pool_t *pool, int is_private_key, const char *kid, const char *filename, apr_jwk_t **j_jwk, apr_jwt_error_t *err) { BIO *input = NULL; apr_jwk_key_rsa_t *key = NULL; apr_byte_t rv = FALSE; if ((input = BIO_new(BIO_s_file())) == NULL) { apr_jwt_error_openssl(err, "BIO_new/BIO_s_file"); goto end; } if (BIO_read_filename(input, filename) <= 0) { apr_jwt_error_openssl(err, "BIO_read_filename"); goto end; } if (apr_jwk_rsa_bio_to_key(pool, input, &key, is_private_key, err) == FALSE) goto end; /* allocate memory for the JWK */ *j_jwk = apr_pcalloc(pool, sizeof(apr_jwk_t)); apr_jwk_t *jwk = *j_jwk; jwk->type = APR_JWK_KEY_RSA; jwk->key.rsa = key; if (kid != NULL) { jwk->kid = apr_pstrdup(pool, kid); } else { /* calculate a unique key identifier (kid) by fingerprinting the key params */ // TODO: based just on sha1 hash of modulus "n" now..., could do this based on jwk->value.str if (apr_jwk_hash_and_base64urlencode(pool, key->modulus, key->modulus_len, &jwk->kid, err) == FALSE) goto end; } rv = TRUE; end: if (input) BIO_free(input); return rv; }
/* * parse an RSA JWK in X.509 format (x5c) */ static apr_byte_t apr_jwk_parse_rsa_x5c(apr_pool_t *pool, apr_jwk_t *jwk) { apr_byte_t rv = FALSE; /* get the "x5c" array element from the JSON object */ json_t *v = json_object_get(jwk->value.json, "x5c"); if ((v == NULL) || (!json_is_array(v))) return FALSE; /* take the first element of the array */ v = json_array_get(v, 0); if ((v == NULL) || (!json_is_string(v))) return FALSE; const char *s_x5c = json_string_value(v); /* PEM-format it */ const int len = 75; int i = 0; char *s = apr_psprintf(pool, "-----BEGIN CERTIFICATE-----\n"); while (i < strlen(s_x5c)) { s = apr_psprintf(pool, "%s%s\n", s, apr_pstrndup(pool, s_x5c + i, len)); i += len; } s = apr_psprintf(pool, "%s-----END CERTIFICATE-----\n", s); BIO *input = NULL; /* put it in BIO memory */ if ((input = BIO_new(BIO_s_mem())) == NULL) return FALSE; if (BIO_puts(input, s) <= 0) { BIO_free(input); return FALSE; } /* do the actual parsing */ rv = apr_jwk_rsa_bio_to_key(pool, input, &jwk->key.rsa, FALSE); BIO_free(input); return rv; }
/* * convert PEM formatted public/private key file to JSON string representation */ static apr_byte_t apr_jwk_pem_to_json_impl(apr_pool_t *pool, const char *filename, char **s_jwk, char**s_kid, int is_private_key) { BIO *input = NULL; apr_jwk_key_rsa_t *key = NULL; apr_byte_t rv = FALSE; if ((input = BIO_new(BIO_s_file())) == NULL) goto end; if (BIO_read_filename(input, filename) <= 0) goto end; if (apr_jwk_rsa_bio_to_key(pool, input, &key, is_private_key) == FALSE) goto end; rv = apr_jwk_rsa_to_json(pool, key, s_jwk, s_kid); end: if (input) BIO_free(input); return rv; }
/* * parse an RSA JWK in X.509 format (x5c) */ static apr_byte_t apr_jwk_parse_rsa_x5c(apr_pool_t *pool, json_t *json, apr_jwk_t *jwk, apr_jwt_error_t *err) { apr_byte_t rv = FALSE; /* get the "x5c" array element from the JSON object */ json_t *v = json_object_get(json, "x5c"); if (v == NULL) { apr_jwt_error(err, "JSON key \"%s\" could not be found", "x5c"); return FALSE; } if (!json_is_array(v)) { apr_jwt_error(err, "JSON key \"%s\" was found but its value is not a JSON array", "x5c"); return FALSE; } /* take the first element of the array */ v = json_array_get(v, 0); if (v == NULL) { apr_jwt_error(err, "first element in JSON array is \"null\""); return FALSE; } if (!json_is_string(v)) { apr_jwt_error(err, "first element in array is not a JSON string"); return FALSE; } const char *s_x5c = json_string_value(v); /* PEM-format it */ const int len = 75; int i = 0; char *s = apr_psprintf(pool, "-----BEGIN CERTIFICATE-----\n"); while (i < strlen(s_x5c)) { s = apr_psprintf(pool, "%s%s\n", s, apr_pstrndup(pool, s_x5c + i, len)); i += len; } s = apr_psprintf(pool, "%s-----END CERTIFICATE-----\n", s); BIO *input = NULL; /* put it in BIO memory */ if ((input = BIO_new(BIO_s_mem())) == NULL) { apr_jwt_error_openssl(err, "memory allocation BIO_new/BIO_s_mem"); return FALSE; } if (BIO_puts(input, s) <= 0) { BIO_free(input); apr_jwt_error_openssl(err, "BIO_puts"); return FALSE; } /* do the actual parsing */ rv = apr_jwk_rsa_bio_to_key(pool, input, &jwk->key.rsa, FALSE, err); BIO_free(input); return rv; }