static void cleanup_siglist (struct sig **sig, char *keyid) { struct sig **last = sig; struct sig *p, *q; for (p = *sig; p; p = q) { q = p->next; if (!strcmp (keyid, p->id) || check_sig_id (p->next, p->id)) { *last = p->next; p->next = NULL; free_sig (&p); } else last = &p->next; } }
static void do_key (struct key *k) { struct sig *interesting_signatures = NULL, *sigp; struct uid *uidp; if (k->rev) return; for (uidp = k->uids; uidp; uidp = uidp->next) if (DontRequireSelfSig || check_selfsig (uidp, k)) join_siglists (&interesting_signatures, &uidp->sigs); cleanup_siglist (&interesting_signatures, k->id); if (interesting_signatures) { printf ("p%s\n", k->id); for (sigp = interesting_signatures; sigp; sigp = sigp->next) printf ("s%s\n", sigp->id); } free_sig (&interesting_signatures); free_uid (&k->uids); }
/** * u2fs_registration_verify: * @ctx: a context handle, from u2fs_init(). * @response: a U2F registration response message Base64 encoded. * @output: pointer to output structure containing the relevant data for a well formed request. Memory should be free'd. * * Get a U2F registration response and check its validity. * * Returns: On success %U2FS_OK (integer 0) is returned and @output is filled up with the user public key, the key handle and the attestation certificate. On errors * a #u2fs_rc error code. */ u2fs_rc u2fs_registration_verify(u2fs_ctx_t * ctx, const char *response, u2fs_reg_res_t ** output) { char *registrationData; char *clientData; char *clientData_decoded; unsigned char *user_public_key; size_t keyHandle_len; char *keyHandle; char *origin; char *challenge; char buf[_B64_BUFSIZE]; unsigned char c = 0; u2fs_X509_t *attestation_certificate; u2fs_ECDSA_t *signature; u2fs_EC_KEY_t *key; u2fs_rc rc; if (ctx == NULL || response == NULL || output == NULL) return U2FS_MEMORY_ERROR; key = NULL; clientData_decoded = NULL; challenge = NULL; origin = NULL; attestation_certificate = NULL; user_public_key = NULL; signature = NULL; registrationData = NULL; clientData = NULL; keyHandle = NULL; *output = NULL; rc = parse_registration_response(response, ®istrationData, &clientData); if (rc != U2FS_OK) goto failure; if (debug) { fprintf(stderr, "registrationData: %s\n", registrationData); fprintf(stderr, "clientData: %s\n", clientData); } rc = parse_registrationData(registrationData, &user_public_key, &keyHandle_len, &keyHandle, &attestation_certificate, &signature); if (rc != U2FS_OK) goto failure; rc = extract_EC_KEY_from_X509(attestation_certificate, &key); if (rc != U2FS_OK) goto failure; //TODO Add certificate validation rc = decode_clientData(clientData, &clientData_decoded); if (rc != U2FS_OK) goto failure; rc = parse_clientData(clientData_decoded, &challenge, &origin); if (rc != U2FS_OK) goto failure; if (strcmp(ctx->challenge, challenge) != 0) { rc = U2FS_CHALLENGE_ERROR; goto failure; } if (strcmp(ctx->origin, origin) != 0) { rc = U2FS_ORIGIN_ERROR; goto failure; } struct sha256_state sha_ctx; char challenge_parameter[U2FS_HASH_LEN], application_parameter[U2FS_HASH_LEN]; sha256_init(&sha_ctx); sha256_process(&sha_ctx, (unsigned char *) ctx->appid, strlen(ctx->appid)); sha256_done(&sha_ctx, (unsigned char *) application_parameter); sha256_init(&sha_ctx); sha256_process(&sha_ctx, (unsigned char *) clientData_decoded, strlen(clientData_decoded)); sha256_done(&sha_ctx, (unsigned char *) challenge_parameter); unsigned char dgst[U2FS_HASH_LEN]; sha256_init(&sha_ctx); sha256_process(&sha_ctx, &c, 1); sha256_process(&sha_ctx, (unsigned char *) application_parameter, U2FS_HASH_LEN); sha256_process(&sha_ctx, (unsigned char *) challenge_parameter, U2FS_HASH_LEN); sha256_process(&sha_ctx, (unsigned char *) keyHandle, keyHandle_len); sha256_process(&sha_ctx, user_public_key, U2FS_PUBLIC_KEY_LEN); sha256_done(&sha_ctx, dgst); rc = verify_ECDSA(dgst, U2FS_HASH_LEN, signature, key); if (rc != U2FS_OK) goto failure; free_sig(signature); signature = NULL; *output = calloc(1, sizeof(**output)); if (*output == NULL) { rc = U2FS_MEMORY_ERROR; goto failure; } rc = encode_b64u(keyHandle, keyHandle_len, buf); if (rc != U2FS_OK) goto failure; u2fs_EC_KEY_t *key_ptr; (*output)->keyHandle = strndup(buf, strlen(buf)); rc = decode_user_key(user_public_key, &key_ptr); if (rc != U2FS_OK) goto failure; (*output)->attestation_certificate = dup_cert(attestation_certificate); rc = dump_user_key(key_ptr, &(*output)->publicKey); if (rc != U2FS_OK) goto failure; rc = dump_X509_cert(attestation_certificate, &(*output)->attestation_certificate_PEM); if (rc != U2FS_OK) goto failure; if ((*output)->keyHandle == NULL || (*output)->publicKey == NULL || (*output)->attestation_certificate == NULL) { rc = U2FS_MEMORY_ERROR; goto failure; } free_key(key); key = NULL; free_cert(attestation_certificate); attestation_certificate = NULL; free(clientData_decoded); clientData_decoded = NULL; free(challenge); challenge = NULL; free(origin); origin = NULL; free(user_public_key); user_public_key = NULL; free(registrationData); registrationData = NULL; free(clientData); clientData = NULL; free(keyHandle); keyHandle = NULL; return U2FS_OK; failure: if (key) { free_key(key); key = NULL; } if (clientData_decoded) { free(clientData_decoded); clientData_decoded = NULL; } if (challenge) { free(challenge); challenge = NULL; } if (origin) { free(origin); origin = NULL; } if (attestation_certificate) { free_cert(attestation_certificate); attestation_certificate = NULL; } if (user_public_key) { free(user_public_key); user_public_key = NULL; } if (signature) { free_sig(signature); signature = NULL; } if (registrationData) { free(registrationData); registrationData = NULL; } if (clientData) { free(clientData); clientData = NULL; } if (keyHandle) { free(keyHandle); keyHandle = NULL; } return rc; }
/** * u2fs_authentication_verify: * @ctx: a context handle, from u2fs_init() * @response: pointer to output string with JSON data. * @output: pointer to output structure containing the relevant data for a well formed request. Memory should be free'd. * * Get a U2F authentication response and check its validity. * * Returns: On a successful verification %U2FS_OK (integer 0) is returned and @output is filled with the authentication result (same as the returned value), the counter received from the token and the user presence information. On errors * a #u2fs_rc error code is returned. */ u2fs_rc u2fs_authentication_verify(u2fs_ctx_t * ctx, const char *response, u2fs_auth_res_t ** output) { char *signatureData; char *clientData; char *clientData_decoded; char *keyHandle; char *challenge; char *origin; uint8_t user_presence; uint32_t counter_num; uint32_t counter; u2fs_ECDSA_t *signature; u2fs_rc rc; if (ctx == NULL || response == NULL || output == NULL) return U2FS_MEMORY_ERROR; signatureData = NULL; clientData = NULL; clientData_decoded = NULL; keyHandle = NULL; challenge = NULL; origin = NULL; signature = NULL; *output = NULL; rc = parse_authentication_response(response, &signatureData, &clientData, &keyHandle); if (rc != U2FS_OK) goto failure; if (debug) { fprintf(stderr, "signatureData: %s\n", signatureData); fprintf(stderr, "clientData: %s\n", clientData); fprintf(stderr, "keyHandle: %s\n", keyHandle); } rc = parse_signatureData(signatureData, &user_presence, &counter, &signature); if (rc != U2FS_OK) goto failure; rc = decode_clientData(clientData, &clientData_decoded); if (rc != U2FS_OK) goto failure; rc = parse_clientData(clientData_decoded, &challenge, &origin); if (rc != U2FS_OK) goto failure; if (strcmp(ctx->challenge, challenge) != 0) { rc = U2FS_CHALLENGE_ERROR; goto failure; } if (strcmp(ctx->origin, origin) != 0) { rc = U2FS_ORIGIN_ERROR; goto failure; } struct sha256_state sha_ctx; char challenge_parameter[U2FS_HASH_LEN], application_parameter[U2FS_HASH_LEN]; sha256_init(&sha_ctx); sha256_process(&sha_ctx, (unsigned char *) ctx->appid, strlen(ctx->appid)); sha256_done(&sha_ctx, (unsigned char *) application_parameter); sha256_init(&sha_ctx); sha256_process(&sha_ctx, (unsigned char *) clientData_decoded, strlen(clientData_decoded)); sha256_done(&sha_ctx, (unsigned char *) challenge_parameter); unsigned char dgst[U2FS_HASH_LEN]; sha256_init(&sha_ctx); sha256_process(&sha_ctx, (unsigned char *) application_parameter, U2FS_HASH_LEN); sha256_process(&sha_ctx, (unsigned char *) &user_presence, 1); sha256_process(&sha_ctx, (unsigned char *) &counter, U2FS_COUNTER_LEN); sha256_process(&sha_ctx, (unsigned char *) challenge_parameter, U2FS_HASH_LEN); sha256_done(&sha_ctx, dgst); rc = verify_ECDSA(dgst, U2FS_HASH_LEN, signature, ctx->key); if (rc != U2FS_OK) goto failure; free_sig(signature); signature = NULL; *output = calloc(1, sizeof(**output)); if (*output == NULL) { rc = U2FS_MEMORY_ERROR; goto failure; } counter_num = 0; counter_num |= (counter & 0xFF000000) >> 24; counter_num |= (counter & 0x00FF0000) >> 8; counter_num |= (counter & 0x0000FF00) << 8; counter_num |= (counter & 0x000000FF) << 24; (*output)->verified = U2FS_OK; (*output)->user_presence = user_presence; (*output)->counter = counter_num; free(origin); origin = NULL; free(challenge); challenge = NULL; free(keyHandle); keyHandle = NULL; free(signatureData); signatureData = NULL; free(clientData); clientData = NULL; free(clientData_decoded); clientData_decoded = NULL; return U2FS_OK; failure: if (clientData_decoded) { free(clientData_decoded); clientData_decoded = NULL; } if (challenge) { free(challenge); challenge = NULL; } if (origin) { free(origin); origin = NULL; } if (signature) { free_sig(signature); signature = NULL; } if (signatureData) { free(signatureData); signatureData = NULL; } if (clientData) { free(clientData); clientData = NULL; } if (keyHandle) { free(keyHandle); keyHandle = NULL; } return rc; }