📄 pkcs15-lib.c
字号:
return r;}static intsc_pkcs15init_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile, unsigned int type, sc_pkcs15_der_t *data, struct sc_path *path){ struct sc_file *file = NULL; unsigned int index; int r; /* Get the number of objects of this type already on this card */ index = sc_pkcs15_get_objects(p15card, type & SC_PKCS15_TYPE_CLASS_MASK, NULL, 0); /* Set the SO PIN reference from card */ if ((r = set_so_pin_from_card(p15card, profile)) < 0) return r; /* Allocate data file */ r = profile->ops->new_file(profile, p15card->card, type, index, &file); if (r < 0) { p15init_error("Unable to allocate file"); goto done; } if (file->path.count == 0) { file->path.index = 0; file->path.count = -1; } r = sc_pkcs15init_update_file(profile, p15card->card, file, data->value, data->len); *path = file->path;done: if (file) sc_file_free(file); return r;}/* * Map X509 keyUsage extension bits to PKCS#15 keyUsage bits */static unsigned int x509_to_pkcs15_private_key_usage[16] = { SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER, /* digitalSignature */ SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, /* NonRepudiation */ SC_PKCS15_PRKEY_USAGE_UNWRAP, /* keyEncipherment */ SC_PKCS15_PRKEY_USAGE_DECRYPT, /* dataEncipherment */ SC_PKCS15_PRKEY_USAGE_DERIVE, /* keyAgreement */ SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER, /* keyCertSign */ SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER, /* cRLSign */};static unsigned int x509_to_pkcs15_public_key_usage[16] = { SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, /* digitalSignature */ SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, /* NonRepudiation */ SC_PKCS15_PRKEY_USAGE_WRAP, /* keyEncipherment */ SC_PKCS15_PRKEY_USAGE_ENCRYPT, /* dataEncipherment */ SC_PKCS15_PRKEY_USAGE_DERIVE, /* keyAgreement */ SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, /* keyCertSign */ SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, /* cRLSign */};static intsc_pkcs15init_map_usage(unsigned long x509_usage, int _private){ unsigned int p15_usage, n, *bits; bits = _private? x509_to_pkcs15_private_key_usage : x509_to_pkcs15_public_key_usage; for (n = p15_usage = 0; n < 16; n++) { if (x509_usage & (1 << n)) p15_usage |= bits[n]; } return p15_usage;}/* * Compute modulus length */size_tsc_pkcs15init_keybits(sc_pkcs15_bignum_t *bn){ unsigned int mask, bits; if (!bn || !bn->len) return 0; bits = bn->len << 3; for (mask = 0x80; !(bn->data[0] & mask); mask >>= 1) bits--; return bits;}/* * Check whether the card has native crypto support for this key. */static int__check_key_compatibility(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey *key, unsigned int x509_usage, unsigned int key_length, unsigned int flags){ struct sc_algorithm_info *info; unsigned int count; int bad_usage = 0; count = p15card->card->algorithm_count; for (info = p15card->card->algorithms; count--; info++) { /* XXX: check for equality, or <= ? */ if (info->algorithm != key->algorithm || info->key_length != key_length || (info->flags & flags) != flags) continue; if (key->algorithm == SC_ALGORITHM_RSA && info->u._rsa.exponent != 0) { sc_pkcs15_bignum_t *e = &key->u.rsa.exponent; unsigned long exponent = 0; unsigned int n; if (e->len > 4) continue; for (n = 0; n < e->len; n++) { exponent <<= 8; exponent |= e->data[n]; } if (info->u._rsa.exponent != exponent) continue; } /* Some cards will not support keys to do * both sign/decrypt. * For the convenience of the user, catch these * here. */ if (info->flags & SC_ALGORITHM_NEED_USAGE) { unsigned int usage; usage = sc_pkcs15init_map_usage(x509_usage, 1); if ((usage & (SC_PKCS15_PRKEY_USAGE_UNWRAP |SC_PKCS15_PRKEY_USAGE_DECRYPT)) && (usage & SC_PKCS15_PRKEY_USAGE_SIGN)) { bad_usage = 1; continue; } } return 1; } return bad_usage? -1 : 0;}static intcheck_key_compatibility(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey *key, unsigned int x509_usage, unsigned int key_length, unsigned int flags){ int res; res = __check_key_compatibility(p15card, key, x509_usage, key_length, flags); if (res < 0) { p15init_error("This device requires that keys have a " "specific key usage.\n" "Keys can be used for either signature or decryption, " "but not both.\n" "Please specify a key usage.\n"); res = 0; } return res;}intsc_pkcs15init_requires_restrictive_usage(struct sc_pkcs15_card *p15card, struct sc_pkcs15init_prkeyargs *keyargs, unsigned int key_length){ int res; if (key_length == 0) key_length = prkey_bits(&keyargs->key); res = __check_key_compatibility(p15card, &keyargs->key, keyargs->x509_usage, key_length, 0); return res < 0;}/* * Check RSA key for consistency, and compute missing * CRT elements */intprkey_fixup_rsa(struct sc_pkcs15_prkey_rsa *key){ if (!key->modulus.len || !key->exponent.len || !key->d.len || !key->p.len || !key->q.len) { p15init_error("Missing private RSA coefficient"); return SC_ERROR_INVALID_ARGUMENTS; }#ifdef HAVE_OPENSSL#define GETBN(dst, src, mem) \ do { dst.len = BN_num_bytes(src); \ assert(dst.len <= sizeof(mem)); \ BN_bn2bin(src, dst.data = mem); \ } while (0) /* Generate additional parameters. * At least the GPK seems to need the full set of CRT * parameters; storing just the private exponent produces * invalid signatures. * The cryptoflex does not seem to be able to do any sort * of RSA without the full set of CRT coefficients either */ if (!key->dmp1.len || !key->dmq1.len || !key->iqmp.len) { static u8 dmp1[256], dmq1[256], iqmp[256]; RSA *rsa; BIGNUM *aux = BN_new(); BN_CTX *ctx = BN_CTX_new(); rsa = RSA_new(); rsa->n = BN_bin2bn(key->modulus.data, key->modulus.len, 0); rsa->e = BN_bin2bn(key->exponent.data, key->exponent.len, 0); rsa->d = BN_bin2bn(key->d.data, key->d.len, 0); rsa->p = BN_bin2bn(key->p.data, key->p.len, 0); rsa->q = BN_bin2bn(key->q.data, key->q.len, 0); if (!rsa->dmp1) rsa->dmp1 = BN_new(); if (!rsa->dmq1) rsa->dmq1 = BN_new(); if (!rsa->iqmp) rsa->iqmp = BN_new(); aux = BN_new(); ctx = BN_CTX_new(); BN_sub(aux, rsa->q, BN_value_one()); BN_mod(rsa->dmq1, rsa->d, aux, ctx); BN_sub(aux, rsa->p, BN_value_one()); BN_mod(rsa->dmp1, rsa->d, aux, ctx); BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx); BN_clear_free(aux); BN_CTX_free(ctx); /* Not thread safe, but much better than a memory leak */ GETBN(key->dmp1, rsa->dmp1, dmp1); GETBN(key->dmq1, rsa->dmq1, dmq1); GETBN(key->iqmp, rsa->iqmp, iqmp); RSA_free(rsa); }#undef GETBN#endif return 0;}static intprkey_fixup(sc_pkcs15_prkey_t *key){ switch (key->algorithm) { case SC_ALGORITHM_RSA: return prkey_fixup_rsa(&key->u.rsa); case SC_ALGORITHM_DSA: /* for now */ return 0; } return 0;}static intprkey_bits(sc_pkcs15_prkey_t *key){ switch (key->algorithm) { case SC_ALGORITHM_RSA: return sc_pkcs15init_keybits(&key->u.rsa.modulus); case SC_ALGORITHM_DSA: return sc_pkcs15init_keybits(&key->u.dsa.q); } p15init_error("Unsupported key algorithm.\n"); return SC_ERROR_NOT_SUPPORTED;}static intprkey_pkcs15_algo(sc_pkcs15_prkey_t *key){ switch (key->algorithm) { case SC_ALGORITHM_RSA: return SC_PKCS15_TYPE_PRKEY_RSA; case SC_ALGORITHM_DSA: return SC_PKCS15_TYPE_PRKEY_DSA; } p15init_error("Unsupported key algorithm.\n"); return SC_ERROR_NOT_SUPPORTED;}static struct sc_pkcs15_df *find_df_by_type(struct sc_pkcs15_card *p15card, int type){ struct sc_pkcs15_df *df = p15card->df_list; while (df != NULL && df->type != type) df = df->next; return df;}intselect_id(struct sc_pkcs15_card *p15card, int type, struct sc_pkcs15_id *id){ unsigned int nid = DEFAULT_ID; struct sc_pkcs15_object *dummy; int r, user_provided; int (*func)(struct sc_pkcs15_card *, const struct sc_pkcs15_id *, struct sc_pkcs15_object **); switch (type) { case SC_PKCS15_TYPE_PRKEY: func = sc_pkcs15_find_prkey_by_id; break; case SC_PKCS15_TYPE_PUBKEY: func = sc_pkcs15_find_pubkey_by_id; break; case SC_PKCS15_TYPE_CERT: func = sc_pkcs15_find_cert_by_id; break; case SC_PKCS15_TYPE_DATA_OBJECT: func = sc_pkcs15_find_data_object_by_id; break; default: return SC_ERROR_INVALID_ARGUMENTS; } user_provided = (id->len != 0); while (nid < 255) { if (!user_provided) { id->value[0] = nid++; id->len = 1; } r = func(p15card, id, &dummy); if (r == SC_ERROR_OBJECT_NOT_FOUND) return 0; if (user_provided) return SC_ERROR_ID_NOT_UNIQUE; } return SC_ERROR_TOO_MANY_OBJECTS;}/* * Update EF(DIR) */static intsc_pkcs15init_update_dir(struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_app_info *app){ struct sc_card *card = p15card->card; int r, retry = 1; do { struct sc_file *dir_file; struct sc_path path; card->ctx->log_errors = 0; r = sc_enum_apps(card); card->ctx->log_errors = 1; if (r != SC_ERROR_FILE_NOT_FOUND) break; sc_format_path("3F002F00", &path); if (sc_profile_get_file_by_path(profile, &path, &dir_file) < 0) return r; r = sc_pkcs15init_update_file(profile, card, dir_file, NULL, 0); sc_file_free(dir_file); } while (retry--); if (r >= 0) { card->app[card->app_count++] = app; r = sc_update_dir(card, NULL); } return r;}static intsc_pkcs15init_update_tokeninfo(struct sc_pkcs15_card *p15card, struct sc_profile *profile){ struct sc_card *card = p15card->card; u8 *buf = NULL; size_t size; int r; r = sc_pkcs15_encode_tokeninfo(card->ctx, p15card, &buf, &size); if (r >= 0) r = sc_pkcs15init_update_file(profile, card, p15card->file_tokeninfo, buf, size); if (buf) free(buf); return r;}static intsc_pkcs15init_update_odf(struct sc_pkcs15_card *p15card, struct sc_profile *profile){ struct sc_card *card = p15card->card; u8 *buf = NULL; size_t size; int r; r = sc_pkcs15_encode_odf(card->ctx, p15card, &buf, &size); if (r >= 0) r = sc_pkcs15init_update_file(profile, card, p15card->file_odf, buf, size); if (buf) free(buf); return r;}static intsc_pkcs15init_add_object(struct sc_pkcs15_card *p15card, struct sc_profile *profile, unsigned int df_type, struct sc_pkcs15_object *object){ struct sc_pkcs15_df *df; struct sc_card *card = p15card->card; struct sc_file *file = NULL, *pfile; u8 *buf = NULL; size_t bufsize; int update_odf = 0, r = 0; df = find_df_by_type(p15card, df_type); if (df == NULL) { file = profile->df[df_type]; if (file == NULL) { p15init_error("Profile doesn't define a DF file %u", df_type); return SC_ERROR_NOT_SUPPORTED; } sc_pkcs15_add_df(p15card, df_type, &file->path, file); df = find_df_by_type(p15card, df_type); assert(df != NULL); update_odf = 1; } if (object) { object->df = df; r = sc_pkcs15_add_object(p15card, object); if (r < 0) return r; } if (!sc_profile_get_file_by_path(profile, &df->path, &pfile)) file = pfile; r = sc_pkcs15_encode_df(card->ctx, p15card, df, &buf, &bufsize); if (r >= 0) { r = sc_pkcs15init_update_file(profile, card, file, buf, bufsize); free(buf); } if (pfile) sc_file_free(pfile); /* Now update the ODF if we have to */ if (r >= 0 && update_odf) r = sc_pkcs15init_update_odf(p15card, profile); return r;}intsc_pkcs15init_change_attrib(struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_pkcs15_object *object, int new_attrib_type, void *new_value, int new_len){ struct sc_card *card = p15card->card; u8 *buf = NULL; size_t bufsize; int df_type, r = 0; struct sc_pkcs15_df *df; if (object == NULL || object->df == NULL) return SC_ERROR_OBJECT_NOT_FOUND; df_type = object->df->type; df = find_df_by_type(p15card, df_type); if (df == NULL) return SC_ERROR_OBJECT_NOT_FOUND; switch(new_attrib_type) { case P15_ATTR_TYPE_LABEL: if (new_len >= SC_PKCS15_MAX_LABEL_SIZE) return SC_ERROR_INVALID_ARGUMENTS; memcpy(object->label, new_value, new_len); object->label[new_len] = '\0'; break; case P15_ATTR_TYPE_ID: switch(df_type) { case SC_PKCS15_PRKDF: ((sc_pkcs15_prkey_info_t *) object->data)->id = *((sc_pkcs15_id_t *) new_value); break; case SC_PKCS15_PUKDF: case SC_PKCS15_PUKDF_TRUSTED: ((sc_pkcs15_pubkey_info_t *) object->data)->id = *((sc_pkcs15_id_t *) new_value); break; case SC_PKCS15_CDF: case SC_PKCS15_CDF_TRUSTED: case SC_PKCS15_CDF_USEFUL: ((sc_pkcs15_cert_info_t *) object->data)->id = *((sc_pkcs15_id_t *) new_value); break; default: return SC_ERROR_NOT_SUPPORTED; } break; default: return SC_ERROR_NOT_SUPPORTED; } r = sc_pkcs15_encode_df(card->ctx, p15card, df, &buf, &bufsize); if (r >= 0) { r = sc_pkcs15init_update_file(profile, card, df->file, buf, bufsize); free(buf); } return r < 0 ? r : 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -