int EAC_CTX_init_ef_cardsecurity(const unsigned char *ef_cardsecurity, size_t ef_cardsecurity_len, EAC_CTX *ctx) { PKCS7 *p7 = NULL, *signed_data; ASN1_OCTET_STRING *os; int r = 0; check(ef_cardsecurity, "Invalid arguments"); if (!d2i_PKCS7(&p7, &ef_cardsecurity, ef_cardsecurity_len) || !PKCS7_type_is_signed(p7)) goto err; if (ctx && ctx->ca_ctx && !(ctx->ca_ctx->flags & CA_FLAG_DISABLE_PASSIVE_AUTH)) check((CA_passive_authentication(ctx, p7) == 1), "Failed to perform passive authentication"); signed_data = p7->d.sign->contents; if (OBJ_obj2nid(signed_data->type) != NID_id_SecurityObject || ASN1_TYPE_get(signed_data->d.other) != V_ASN1_OCTET_STRING) goto err; os = signed_data->d.other->value.octet_string; if (!EAC_CTX_init_ef_cardaccess(os->data, os->length, ctx) || !ctx || !ctx->ca_ctx || !ctx->ca_ctx->ka_ctx) goto err; r = 1; err: if (p7) PKCS7_free(p7); return r; }
int main(int argc, char *argv[]) { int r; BIO *bio = NULL; PACE_SEC *secret = NULL; EAC_CTX *picc_ctx = NULL, *pcd_ctx = NULL; BUF_MEM *enc_nonce = NULL, *pcd_mapping_data = NULL, *picc_mapping_data = NULL, *pcd_ephemeral_pubkey = NULL, *picc_ephemeral_pubkey = NULL, *pcd_token = NULL, *picc_token = NULL; EAC_init(); puts("EF.CardAccess:"); bio = BIO_new_fp(stdout, BIO_NOCLOSE|BIO_FP_TEXT); BIO_dump_indent(bio, (char *) EF_CARDACCESS, sizeof EF_CARDACCESS, 4); secret = PACE_SEC_new(PIN, strlen(PIN), PACE_PIN); puts("Secret:"); PACE_SEC_print_private(bio, secret, 4); picc_ctx = EAC_CTX_new(); pcd_ctx = EAC_CTX_new(); EAC_CTX_init_ef_cardaccess(EF_CARDACCESS, sizeof EF_CARDACCESS, pcd_ctx); EAC_CTX_init_ef_cardaccess(EF_CARDACCESS, sizeof EF_CARDACCESS, picc_ctx); puts("PACE step 1"); enc_nonce = PACE_STEP1_enc_nonce(picc_ctx, secret); puts("PACE step 2"); PACE_STEP2_dec_nonce(pcd_ctx, secret, enc_nonce); puts("PACE step 3A"); pcd_mapping_data = PACE_STEP3A_generate_mapping_data(pcd_ctx); picc_mapping_data = PACE_STEP3A_generate_mapping_data(picc_ctx); PACE_STEP3A_map_generator(pcd_ctx, picc_mapping_data); PACE_STEP3A_map_generator(picc_ctx, pcd_mapping_data); puts("PACE step 3B"); pcd_ephemeral_pubkey = PACE_STEP3B_generate_ephemeral_key(pcd_ctx); picc_ephemeral_pubkey = PACE_STEP3B_generate_ephemeral_key(picc_ctx); PACE_STEP3B_compute_shared_secret(pcd_ctx, picc_ephemeral_pubkey); PACE_STEP3B_compute_shared_secret(picc_ctx, pcd_ephemeral_pubkey); puts("PACE step 3C"); PACE_STEP3C_derive_keys(pcd_ctx); PACE_STEP3C_derive_keys(picc_ctx); puts("PACE step 3D"); pcd_token = PACE_STEP3D_compute_authentication_token(pcd_ctx, picc_ephemeral_pubkey); picc_token = PACE_STEP3D_compute_authentication_token(picc_ctx, pcd_ephemeral_pubkey); r = PACE_STEP3D_verify_authentication_token(pcd_ctx, picc_token); if (r == 1) r = PACE_STEP3D_verify_authentication_token(picc_ctx, pcd_token); puts("PICC's EAC_CTX:"); EAC_CTX_print_private(bio, picc_ctx, 4); puts("PCD's EAC_CTX:"); EAC_CTX_print_private(bio, pcd_ctx, 4); EAC_CTX_clear_free(pcd_ctx); EAC_CTX_clear_free(picc_ctx); PACE_SEC_clear_free(secret); EAC_cleanup(); EAC_CTX_clear_free(pcd_ctx); EAC_CTX_clear_free(picc_ctx); PACE_SEC_clear_free(secret); if (bio) BIO_free_all(bio); if (enc_nonce) BUF_MEM_free(enc_nonce); if (pcd_mapping_data) BUF_MEM_free(pcd_mapping_data); if (picc_mapping_data) BUF_MEM_free(picc_mapping_data); if (pcd_ephemeral_pubkey) BUF_MEM_free(pcd_ephemeral_pubkey); if (picc_ephemeral_pubkey) BUF_MEM_free(picc_ephemeral_pubkey); if (pcd_token) BUF_MEM_free(pcd_token); if (picc_token) BUF_MEM_free(picc_token); if (r != 1) return 1; return 0; }