static void test_rfc4648_test_vectors(void) { char *b64; b64 = grpc_base64_encode("", 0, 0, 0); GPR_ASSERT(strcmp("", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("f", 1, 0, 0); GPR_ASSERT(strcmp("Zg==", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("fo", 2, 0, 0); GPR_ASSERT(strcmp("Zm8=", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("foo", 3, 0, 0); GPR_ASSERT(strcmp("Zm9v", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("foob", 4, 0, 0); GPR_ASSERT(strcmp("Zm9vYg==", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("fooba", 5, 0, 0); GPR_ASSERT(strcmp("Zm9vYmE=", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("foobar", 6, 0, 0); GPR_ASSERT(strcmp("Zm9vYmFy", b64) == 0); gpr_free(b64); }
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 char *encoded_jwt_header(const char *key_id, const char *algorithm) { grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json *child = NULL; char *json_str = NULL; char *result = NULL; child = create_child(NULL, json, "alg", algorithm, GRPC_JSON_STRING); child = create_child(child, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING); create_child(child, json, "kid", key_id, GRPC_JSON_STRING); json_str = grpc_json_dump_to_string(json, 0); result = grpc_base64_encode(json_str, strlen(json_str), 1, 0); gpr_free(json_str); grpc_json_destroy(json); 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); }
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); } }
char *compute_and_encode_signature(const grpc_auth_json_key *json_key, const char *signature_algorithm, const char *to_sign) { const EVP_MD *md = openssl_digest_from_algorithm(signature_algorithm); EVP_MD_CTX *md_ctx = NULL; EVP_PKEY *key = EVP_PKEY_new(); size_t sig_len = 0; unsigned char *sig = NULL; char *result = NULL; if (md == NULL) return NULL; md_ctx = EVP_MD_CTX_create(); if (md_ctx == NULL) { gpr_log(GPR_ERROR, "Could not create MD_CTX"); goto end; } EVP_PKEY_set1_RSA(key, json_key->private_key); if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, key) != 1) { gpr_log(GPR_ERROR, "DigestInit failed."); goto end; } if (EVP_DigestSignUpdate(md_ctx, to_sign, strlen(to_sign)) != 1) { gpr_log(GPR_ERROR, "DigestUpdate failed."); goto end; } if (EVP_DigestSignFinal(md_ctx, NULL, &sig_len) != 1) { gpr_log(GPR_ERROR, "DigestFinal (get signature length) failed."); goto end; } sig = gpr_malloc(sig_len); if (EVP_DigestSignFinal(md_ctx, sig, &sig_len) != 1) { gpr_log(GPR_ERROR, "DigestFinal (signature compute) failed."); goto end; } result = grpc_base64_encode(sig, sig_len, 1, 0); end: if (key != NULL) EVP_PKEY_free(key); if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); if (sig != NULL) gpr_free(sig); return result; }
static char *encoded_jwt_claim(const grpc_auth_json_key *json_key, const char *audience, gpr_timespec token_lifetime, const char *scope) { grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json *child = NULL; char *json_str = NULL; char *result = NULL; gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); gpr_timespec expiration = gpr_time_add(now, token_lifetime); char now_str[GPR_LTOA_MIN_BUFSIZE]; char expiration_str[GPR_LTOA_MIN_BUFSIZE]; if (gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime()) > 0) { gpr_log(GPR_INFO, "Cropping token lifetime to maximum allowed value."); expiration = gpr_time_add(now, grpc_max_auth_token_lifetime()); } int64_ttoa(now.tv_sec, now_str); int64_ttoa(expiration.tv_sec, expiration_str); child = create_child(NULL, json, "iss", json_key->client_email, GRPC_JSON_STRING); if (scope != NULL) { child = create_child(child, json, "scope", scope, GRPC_JSON_STRING); } else { /* Unscoped JWTs need a sub field. */ child = create_child(child, json, "sub", json_key->client_email, GRPC_JSON_STRING); } child = create_child(child, json, "aud", audience, GRPC_JSON_STRING); child = create_child(child, json, "iat", now_str, GRPC_JSON_NUMBER); create_child(child, json, "exp", expiration_str, GRPC_JSON_NUMBER); json_str = grpc_json_dump_to_string(json, 0); result = grpc_base64_encode(json_str, strlen(json_str), 1, 0); gpr_free(json_str); grpc_json_destroy(json); return result; }