int sc_pkcs15emu_object_add(sc_pkcs15_card_t *p15card, unsigned int type, const sc_pkcs15_object_t *in_obj, const void *data) { sc_pkcs15_object_t *obj; unsigned int df_type; size_t data_len; obj = calloc(1, sizeof(*obj)); if (!obj) return SC_ERROR_OUT_OF_MEMORY; memcpy(obj, in_obj, sizeof(*obj)); obj->type = type; switch (type & SC_PKCS15_TYPE_CLASS_MASK) { case SC_PKCS15_TYPE_AUTH: df_type = SC_PKCS15_AODF; data_len = sizeof(struct sc_pkcs15_auth_info); break; case SC_PKCS15_TYPE_PRKEY: df_type = SC_PKCS15_PRKDF; data_len = sizeof(struct sc_pkcs15_prkey_info); break; case SC_PKCS15_TYPE_PUBKEY: df_type = SC_PKCS15_PUKDF; data_len = sizeof(struct sc_pkcs15_pubkey_info); break; case SC_PKCS15_TYPE_CERT: df_type = SC_PKCS15_CDF; data_len = sizeof(struct sc_pkcs15_cert_info); break; case SC_PKCS15_TYPE_DATA_OBJECT: df_type = SC_PKCS15_DODF; data_len = sizeof(struct sc_pkcs15_data_info); break; default: sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Unknown PKCS15 object type %d\n", type); free(obj); return SC_ERROR_INVALID_ARGUMENTS; } obj->data = calloc(1, data_len); if (obj->data == NULL) { free(obj); return SC_ERROR_OUT_OF_MEMORY; } memcpy(obj->data, data, data_len); obj->df = sc_pkcs15emu_get_df(p15card, df_type); sc_pkcs15_add_object(p15card, obj); return SC_SUCCESS; }
static int sc_pkcs15emu_add_object(sc_pkcs15_card_t *p15card, int type, const char *label, void *data, const sc_pkcs15_id_t *auth_id, int obj_flags) { sc_pkcs15_object_t *obj; int df_type; obj = calloc(1, sizeof(*obj)); obj->type = type; obj->data = data; if (label) strncpy(obj->label, label, sizeof(obj->label)-1); obj->flags = obj_flags; if (auth_id) obj->auth_id = *auth_id; switch (type & SC_PKCS15_TYPE_CLASS_MASK) { case SC_PKCS15_TYPE_AUTH: df_type = SC_PKCS15_AODF; break; case SC_PKCS15_TYPE_PRKEY: df_type = SC_PKCS15_PRKDF; break; case SC_PKCS15_TYPE_PUBKEY: df_type = SC_PKCS15_PUKDF; break; case SC_PKCS15_TYPE_CERT: df_type = SC_PKCS15_CDF; break; default: sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Unknown PKCS15 object type %d\n", type); free(obj); return SC_ERROR_INVALID_ARGUMENTS; } obj->df = sc_pkcs15emu_get_df(p15card, df_type); sc_pkcs15_add_object(p15card, obj); return 0; }
int sc_pkcs15_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df) { sc_context_t *ctx = p15card->card->ctx; u8 *buf; const u8 *p; size_t bufsize; int r; struct sc_pkcs15_object *obj = NULL; int (* func)(struct sc_pkcs15_card *, struct sc_pkcs15_object *, const u8 **nbuf, size_t *nbufsize) = NULL; switch (df->type) { case SC_PKCS15_PRKDF: func = sc_pkcs15_decode_prkdf_entry; break; case SC_PKCS15_PUKDF: func = sc_pkcs15_decode_pukdf_entry; break; case SC_PKCS15_CDF: case SC_PKCS15_CDF_TRUSTED: case SC_PKCS15_CDF_USEFUL: func = sc_pkcs15_decode_cdf_entry; break; case SC_PKCS15_DODF: func = sc_pkcs15_decode_dodf_entry; break; case SC_PKCS15_AODF: func = sc_pkcs15_decode_aodf_entry; break; } if (func == NULL) { sc_error(ctx, "unknown DF type: %d\n", df->type); return SC_ERROR_INVALID_ARGUMENTS; } if (df->file != NULL) r = sc_pkcs15_read_file(p15card, &df->path, &buf, &bufsize, NULL); else r = sc_pkcs15_read_file(p15card, &df->path, &buf, &bufsize, &df->file); if (r < 0) return r; p = buf; while (bufsize && *p != 0x00) { const u8 *oldp; size_t obj_len; obj = (struct sc_pkcs15_object *) calloc(1, sizeof(struct sc_pkcs15_object)); if (obj == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto ret; } oldp = p; r = func(p15card, obj, &p, &bufsize); if (r) { free(obj); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) { r = 0; break; } sc_perror(ctx, r, "Error decoding DF entry"); goto ret; } obj_len = p - oldp; obj->der.value = (u8 *) malloc(obj_len); if (obj->der.value == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto ret; } memcpy(obj->der.value, oldp, obj_len); obj->der.len = obj_len; obj->df = df; r = sc_pkcs15_add_object(p15card, obj); if (r) { if (obj->data) free(obj->data); free(obj); sc_perror(ctx, r, "Error adding object"); goto ret; } }; ret: free(buf); return r; }
int sc_pkcs15_parse_card_df(struct sc_pkcs15_card *p15card, const unsigned int df_type, const u8 *buf, const size_t in_bufsize) { sc_context_t *ctx = p15card->card->ctx; int r = SC_SUCCESS; size_t bufsize = in_bufsize; struct sc_pkcs15_object *obj = NULL; int (* func)(struct sc_pkcs15_card *, struct sc_pkcs15_object *, const u8 **nbuf, size_t *nbufsize) = NULL; int (* func2)(struct sc_pkcs15_card *p15card, const u8 * buf, size_t buflen) = NULL; if ( ctx->debug ) sc_debug( ctx, "Entering function sc_pkcs15_parse_card_df\n" ); switch (df_type) { case SC_PKCS15_PRKDF: func = sc_pkcs15_decode_prkdf_entry; break; case SC_PKCS15_PUKDF: func = sc_pkcs15_decode_pukdf_entry; break; case SC_PKCS15_CDF: case SC_PKCS15_CDF_TRUSTED: case SC_PKCS15_CDF_USEFUL: func = sc_pkcs15_decode_cdf_entry; break; case SC_PKCS15_DODF: func = sc_pkcs15_decode_dodf_entry; break; case SC_PKCS15_AODF: func = sc_pkcs15_decode_aodf_entry; break; } if (func == NULL) { switch (df_type) { case SC_PKCS15_ODF: func2 = parse_card_odf; break; case SC_PKCS15_TOKENINFO: func2 = parse_card_tokeninfo; break; case SC_PKCS15_UNUSED: func2 = parse_card_unusedspace; break; } if (func2 == NULL) { sc_error(ctx, "unknown DF type: %d\n", df_type); r = SC_ERROR_INVALID_ARGUMENTS; goto ret; } r = func2(p15card, buf, bufsize); if (r!=SC_SUCCESS) { sc_perror(ctx, r, "Error decoding DF entry"); } goto ret; } do { const u8 *oldp; size_t obj_len; obj = (struct sc_pkcs15_object *) calloc(1, sizeof(struct sc_pkcs15_object)); if (obj == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto ret; } oldp = buf; r = func(p15card, obj, &buf, &bufsize); if (r) { free(obj); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) { r = 0; break; } sc_perror(ctx, r, "Error decoding DF entry"); goto ret; } obj_len = buf - oldp; obj->der.value = (u8 *) malloc(obj_len); if (obj->der.value == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto ret; } memcpy(obj->der.value, oldp, obj_len); obj->der.len = obj_len; /* These objects are independent one another*/ obj->df = NULL; r = sc_pkcs15_add_object(p15card, obj); if (r) { if (obj->data) free(obj->data); free(obj); sc_perror(ctx, r, "Error adding object"); goto ret; } } while (bufsize && *buf != 0x00); ret: if (ctx->debug) sc_debug(ctx, "Leaving function sc_pkcs15_parse_card_df\n"); return r; }