📄 pkcs15-etoken.c
字号:
return (sign && decipher)? -1 : 0;}/* * Create a private key object */#define ETOKEN_KEY_OPTIONS 0x02#define ETOKEN_KEY_FLAGS 0x00static intetoken_store_key_component(struct sc_card *card, int algorithm, unsigned int key_id, unsigned int pin_id, unsigned int num, const u8 *data, size_t len, int last){ struct sc_cardctl_etoken_obj_info args; struct tlv tlv; unsigned char buffer[256]; unsigned int n; /* Initialize the TLV encoder */ tlv_init(&tlv, buffer, sizeof(buffer)); /* Object address */ tlv_next(&tlv, 0x83); tlv_add(&tlv, 0x20|num); /* PSO, n-th component */ tlv_add(&tlv, key_id); /* Object parameters */ tlv_next(&tlv, 0x85); tlv_add(&tlv, ETOKEN_KEY_OPTIONS|(last? 0x00 : 0x20)); tlv_add(&tlv, ETOKEN_KEY_FLAGS); tlv_add(&tlv, algorithm); tlv_add(&tlv, 0x00); tlv_add(&tlv, 0xFF); /* use count */ tlv_add(&tlv, 0xFF); /* DEK (whatever this is) */ tlv_add(&tlv, 0x00); tlv_add(&tlv, 0x00); /* AC bytes */ tlv_next(&tlv, 0x86); tlv_add(&tlv, pin_id); /* AC USE */ tlv_add(&tlv, pin_id); /* AC CHANGE */ tlv_add(&tlv, pin_id); /* UNKNOWN */ /* The next 4 AC bytes are sent by the eToken run-time * as well, but aren't documented anywhere. * Key generation won't work without them, however. */ tlv_add(&tlv, 0); tlv_add(&tlv, 0); tlv_add(&tlv, 0); tlv_add(&tlv, 0); /* SM bytes */ tlv_next(&tlv, 0x8B); for (n = 0; n < 16; n++) tlv_add(&tlv, 0xFF); /* key component */ tlv_next(&tlv, 0x8f); tlv_add(&tlv, len+1); tlv_add(&tlv, 0); while (len--) tlv_add(&tlv, *data++); args.data = buffer; args.len = tlv_len(&tlv); return sc_card_ctl(card, SC_CARDCTL_ETOKEN_PUT_DATA_OCI, &args);}static intetoken_store_key(struct sc_profile *profile, struct sc_card *card, int algorithm, unsigned int key_id, struct sc_pkcs15_prkey_rsa *key){ struct sc_pkcs15_pin_info pin_info; int r, pin_id; sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &pin_info); if ((pin_id = pin_info.reference) < 0) pin_id = 0; r = etoken_store_key_component(card, algorithm, key_id, pin_id, 0, key->modulus.data, key->modulus.len, 0); if (r < 0) return r; r = etoken_store_key_component(card, algorithm, key_id, pin_id, 1, key->d.data, key->d.len, 1); return r;}/* * Store a private key */static intetoken_new_key(struct sc_profile *profile, struct sc_card *card, struct sc_pkcs15_prkey *key, unsigned int index, struct sc_pkcs15_prkey_info *info){ struct sc_pkcs15_prkey_rsa *rsa; int algorithm, key_id, r; if (key->algorithm != SC_ALGORITHM_RSA) { error(profile, "eToken supports RSA keys only.\n"); return SC_ERROR_NOT_SUPPORTED; } if (etoken_key_algorithm(info->usage, &algorithm) < 0) { error(profile, "eToken does not support keys " "that can both sign _and_ decrypt."); return SC_ERROR_NOT_SUPPORTED; } rsa = &key->u.rsa; key_id = ETOKEN_KEY_ID(index); r = etoken_store_key(profile, card, algorithm, key_id, rsa); if (r >= 0) { info->path = profile->df_info->file->path; info->key_reference = key_id; } return r;}/* * Allocate a file */static intetoken_new_file(struct sc_profile *profile, struct sc_card *card, unsigned int type, unsigned int num, struct sc_file **out){ struct sc_file *file; struct sc_path *p; char name[64], *tag, *desc; desc = tag = NULL; while (1) { switch (type) { case SC_PKCS15_TYPE_PRKEY_RSA: desc = "RSA private key"; tag = "private-key"; break; case SC_PKCS15_TYPE_PUBKEY_RSA: desc = "RSA public key"; tag = "public-key"; break;#ifdef SC_PKCS15_TYPE_PRKEY_DSA case SC_PKCS15_TYPE_PRKEY_DSA: desc = "DSA private key"; tag = "private-key"; break; case SC_PKCS15_TYPE_PUBKEY_DSA: desc = "DSA public key"; tag = "public-key"; break;#endif case SC_PKCS15_TYPE_PRKEY: desc = "extractable private key"; tag = "extractable-key"; break; case SC_PKCS15_TYPE_CERT: desc = "certificate"; tag = "certificate"; break; case SC_PKCS15_TYPE_DATA_OBJECT: desc = "data object"; tag = "data"; break; } if (tag) break; /* If this is a specific type such as * SC_PKCS15_TYPE_CERT_FOOBAR, fall back to * the generic class (SC_PKCS15_TYPE_CERT) */ if (!(type & ~SC_PKCS15_TYPE_CLASS_MASK)) { error(profile, "File type not supported by card driver"); return SC_ERROR_INVALID_ARGUMENTS; } type &= SC_PKCS15_TYPE_CLASS_MASK; } snprintf(name, sizeof(name), "template-%s", tag); if (sc_profile_get_file(profile, name, &file) < 0) { error(profile, "Profile doesn't define %s template (%s)\n", desc, name); return SC_ERROR_NOT_SUPPORTED; } /* Now construct file from template */ file->id += num; p = &file->path; *p = profile->df_info->file->path; p->value[p->len++] = file->id >> 8; p->value[p->len++] = file->id; *out = file; return 0;}/* * Extract a key component from the public key file populated by * GENERATE KEY PAIR */static intetoken_extract_pubkey(struct sc_card *card, int nr, u8 tag, sc_pkcs15_bignum_t *bn){ u8 buf[256]; int r, count; r = sc_read_record(card, nr, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r < 0) return r; count = r - 4; if (count <= 0 || buf[0] != tag || buf[1] != count + 2 || buf[2] != count + 1 || buf[3] != 0) return SC_ERROR_INTERNAL; bn->len = count; bn->data = (u8 *) malloc(count); memcpy(bn->data, buf + 4, count); return 0;}/* * Key generation */static intetoken_generate_key(struct sc_profile *profile, struct sc_card *card, unsigned int index, unsigned int keybits, sc_pkcs15_pubkey_t *pubkey, struct sc_pkcs15_prkey_info *info){ struct sc_pkcs15_prkey_rsa key_obj; struct sc_cardctl_etoken_genkey_info args; struct sc_file *temp; u8 abignum[RSAKEY_MAX_SIZE]; u8 randbuf[64], key_id; int algorithm, r, delete_it = 0; keybits &= ~7UL; if (keybits > RSAKEY_MAX_BITS) { error(profile, "Unable to generate key, max size is %d\n", RSAKEY_MAX_BITS); return SC_ERROR_INVALID_ARGUMENTS; } if (etoken_key_algorithm(info->usage, &algorithm) < 0) { error(profile, "eToken does not support keys " "that can both sign _and_ decrypt."); return SC_ERROR_NOT_SUPPORTED; } if (sc_profile_get_file(profile, "tempfile", &temp) < 0) { error(profile, "Profile doesn't define temporary file " "for key generation.\n"); return SC_ERROR_NOT_SUPPORTED; } memset(pubkey, 0, sizeof(*pubkey)); if ((r = sc_pkcs15init_create_file(profile, card, temp)) < 0) goto out; delete_it = 1; key_id = ETOKEN_KEY_ID(index); /* Create a key object, initializing components to 0xff */ memset(&key_obj, 0, sizeof(key_obj)); memset(abignum, 0xFF, sizeof(abignum)); key_obj.modulus.data = abignum; key_obj.modulus.len = keybits >> 3; key_obj.d.data = abignum; key_obj.d.len = keybits >> 3; r = etoken_store_key(profile, card, algorithm, key_id, &key_obj); if (r < 0) goto out; memset(&args, 0, sizeof(args));#ifdef notyet if ((r = scrandom_get_data(randbuf, sizeof(randbuf))) < 0) goto out; /* For now, we have to rely on the card's internal number * generator because libscrandom is static, which causes * all sorts of headaches when linking against it * (some platforms don't allow non-PIC code in a shared lib, * such as ia64). */ args.random_data = randbuf; args.random_len = sizeof(randbuf);#endif args.key_id = key_id; args.key_bits = keybits; args.fid = temp->id; r = sc_card_ctl(card, SC_CARDCTL_ETOKEN_GENERATE_KEY, &args); memset(randbuf, 0, sizeof(randbuf)); if (r < 0) goto out; /* extract public key from file and delete it */ if ((r = sc_select_file(card, &temp->path, NULL)) < 0) goto out; r = etoken_extract_pubkey(card, 1, 0x10, &pubkey->u.rsa.modulus); if (r < 0) goto out; r = etoken_extract_pubkey(card, 2, 0x11, &pubkey->u.rsa.exponent); if (r < 0) goto out; pubkey->algorithm = SC_ALGORITHM_RSA; info->key_reference = key_id; info->path = profile->df_info->file->path;out: if (delete_it) { sc_pkcs15init_rmdir(card, profile, temp); } sc_file_free(temp); if (r < 0) { if (pubkey->u.rsa.modulus.data) free (pubkey->u.rsa.modulus.data); if (pubkey->u.rsa.exponent.data) free (pubkey->u.rsa.exponent.data); } return r;}static voiderror(struct sc_profile *profile, const char *fmt, ...){ char buffer[256]; va_list ap; va_start(ap, fmt); vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); if (profile->cbs) profile->cbs->error("%s", buffer);}struct sc_pkcs15init_operations sc_pkcs15init_etoken_operations = { etoken_erase, etoken_init_app, etoken_new_pin, etoken_new_key, etoken_new_file, etoken_generate_key};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -