static void test_url_safe_unsafe_mismtach_failure(void) { unsigned char orig[256]; size_t i; char *b64; gpr_slice orig_decoded; int url_safe = 1; for (i = 0; i < sizeof(orig); i++) orig[i] = (char)i; b64 = grpc_base64_encode(orig, sizeof(orig), url_safe, 0); orig_decoded = grpc_base64_decode(b64, !url_safe); GPR_ASSERT(GPR_SLICE_IS_EMPTY(orig_decoded)); gpr_free(b64); gpr_slice_unref(orig_decoded); b64 = grpc_base64_encode(orig, sizeof(orig), !url_safe, 0); orig_decoded = grpc_base64_decode(b64, url_safe); GPR_ASSERT(GPR_SLICE_IS_EMPTY(orig_decoded)); gpr_free(b64); gpr_slice_unref(orig_decoded); }
static void test_simple_encode_decode_b64(int url_safe, int multiline) { const char *hello = "hello"; char *hello_b64 = grpc_base64_encode(hello, strlen(hello), url_safe, multiline); gpr_slice hello_slice = grpc_base64_decode(hello_b64, url_safe); GPR_ASSERT(GPR_SLICE_LENGTH(hello_slice) == strlen(hello)); GPR_ASSERT(strncmp((const char *)GPR_SLICE_START_PTR(hello_slice), hello, GPR_SLICE_LENGTH(hello_slice)) == 0); gpr_slice_unref(hello_slice); gpr_free(hello_b64); }
static BIGNUM *bignum_from_base64(const char *b64) { BIGNUM *result = NULL; gpr_slice bin; if (b64 == NULL) return NULL; bin = grpc_base64_decode(b64, 1); if (GPR_SLICE_IS_EMPTY(bin)) { gpr_log(GPR_ERROR, "Invalid base64 for big num."); return NULL; } result = BN_bin2bn(GPR_SLICE_START_PTR(bin), GPR_SLICE_LENGTH(bin), NULL); gpr_slice_unref(bin); return result; }
static void corrupt_jwt_sig(char *jwt) { gpr_slice sig; char *bad_b64_sig; uint8_t *sig_bytes; char *last_dot = strrchr(jwt, '.'); GPR_ASSERT(last_dot != NULL); sig = grpc_base64_decode(last_dot + 1, 1); GPR_ASSERT(!GPR_SLICE_IS_EMPTY(sig)); sig_bytes = GPR_SLICE_START_PTR(sig); (*sig_bytes)++; /* Corrupt first byte. */ bad_b64_sig = grpc_base64_encode(GPR_SLICE_START_PTR(sig), GPR_SLICE_LENGTH(sig), 1, 0); memcpy(last_dot + 1, bad_b64_sig, strlen(bad_b64_sig)); gpr_free(bad_b64_sig); gpr_slice_unref(sig); }
void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx, grpc_jwt_verifier *verifier, grpc_pollset *pollset, const char *jwt, const char *audience, grpc_jwt_verification_done_cb cb, void *user_data) { const char *dot = NULL; grpc_json *json; jose_header *header = NULL; grpc_jwt_claims *claims = NULL; grpc_slice header_buffer; grpc_slice claims_buffer; grpc_slice signature; size_t signed_jwt_len; const char *cur = jwt; GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL); dot = strchr(cur, '.'); if (dot == NULL) goto error; json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &header_buffer); if (json == NULL) goto error; header = jose_header_from_json(json, header_buffer); if (header == NULL) goto error; cur = dot + 1; dot = strchr(cur, '.'); if (dot == NULL) goto error; json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &claims_buffer); if (json == NULL) goto error; claims = grpc_jwt_claims_from_json(json, claims_buffer); if (claims == NULL) goto error; signed_jwt_len = (size_t)(dot - jwt); cur = dot + 1; signature = grpc_base64_decode(cur, 1); if (GRPC_SLICE_IS_EMPTY(signature)) goto error; retrieve_key_and_verify( exec_ctx, verifier_cb_ctx_create(verifier, pollset, header, claims, audience, signature, jwt, signed_jwt_len, user_data, cb)); return; error: if (header != NULL) jose_header_destroy(header); if (claims != NULL) grpc_jwt_claims_destroy(claims); cb(user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL); }
static void test_full_range_encode_decode_b64(int url_safe, int multiline) { unsigned char orig[256]; size_t i; char *b64; gpr_slice orig_decoded; for (i = 0; i < sizeof(orig); i++) orig[i] = (char)i; /* Try all the different paddings. */ for (i = 0; i < 3; i++) { b64 = grpc_base64_encode(orig, sizeof(orig) - i, url_safe, multiline); orig_decoded = grpc_base64_decode(b64, url_safe); GPR_ASSERT(GPR_SLICE_LENGTH(orig_decoded) == (sizeof(orig) - i)); GPR_ASSERT(buffers_are_equal(orig, GPR_SLICE_START_PTR(orig_decoded), sizeof(orig) - i)); gpr_slice_unref(orig_decoded); gpr_free(b64); } }
static grpc_json *parse_json_part_from_jwt(const char *str, size_t len, char **scratchpad) { char *b64; char *decoded; grpc_json *json; gpr_slice slice; b64 = gpr_malloc(len + 1); strncpy(b64, str, len); b64[len] = '\0'; slice = grpc_base64_decode(b64, 1); GPR_ASSERT(!GPR_SLICE_IS_EMPTY(slice)); decoded = gpr_malloc(GPR_SLICE_LENGTH(slice) + 1); strncpy(decoded, (const char *)GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice)); decoded[GPR_SLICE_LENGTH(slice)] = '\0'; json = grpc_json_parse_string(decoded); gpr_free(b64); *scratchpad = decoded; gpr_slice_unref(slice); return json; }
static void check_jwt_signature(const char *b64_signature, RSA *rsa_key, const char *signed_data, size_t signed_data_size) { EVP_MD_CTX *md_ctx = EVP_MD_CTX_create(); EVP_PKEY *key = EVP_PKEY_new(); gpr_slice sig = grpc_base64_decode(b64_signature, 1); GPR_ASSERT(!GPR_SLICE_IS_EMPTY(sig)); GPR_ASSERT(GPR_SLICE_LENGTH(sig) == 128); GPR_ASSERT(md_ctx != NULL); GPR_ASSERT(key != NULL); EVP_PKEY_set1_RSA(key, rsa_key); GPR_ASSERT(EVP_DigestVerifyInit(md_ctx, NULL, EVP_sha256(), NULL, key) == 1); GPR_ASSERT(EVP_DigestVerifyUpdate(md_ctx, signed_data, signed_data_size) == 1); GPR_ASSERT(EVP_DigestVerifyFinal(md_ctx, GPR_SLICE_START_PTR(sig), GPR_SLICE_LENGTH(sig)) == 1); gpr_slice_unref(sig); if (key != NULL) EVP_PKEY_free(key); if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); }