libopensc: remove more traces of software token/non-native private key related code.
pkcs15-wrap.c can be removed. Clarified/changed the meaning of "insecure" flag to pkcs15-init tool, which will be needed to explicitly enforce the creation of a key which does not require a PIN. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@5510 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
7179778e22
commit
215c133ba0
|
@ -145,10 +145,6 @@
|
|||
<para>
|
||||
<command>pkcs15-init --store-private-key okir.pem --id 45 --auth-id 01</command>
|
||||
</para>
|
||||
<para>
|
||||
If the key is protected by a pass phrase, <command>pkcs15-init</command>
|
||||
will prompt you for a pass phrase to unlock the key.
|
||||
</para>
|
||||
<para>
|
||||
In addition to storing the private portion of the key on the card,
|
||||
<command>pkcs15-init</command> will also store the the public portion of the
|
||||
|
@ -397,17 +393,6 @@
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--passphrase</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
When downloading a private key, this option can be used to specify
|
||||
the pass phrase to unlock the private key. The same caveat applies
|
||||
here as in the case of the <option>--pin</option> options.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--options-file</option> <emphasis>filename</emphasis></term>
|
||||
<listitem>
|
||||
|
|
|
@ -24,8 +24,7 @@ libopensc_la_SOURCES = \
|
|||
\
|
||||
pkcs15.c pkcs15-cert.c pkcs15-data.c pkcs15-pin.c \
|
||||
pkcs15-prkey.c pkcs15-pubkey.c pkcs15-sec.c \
|
||||
pkcs15-wrap.c pkcs15-algo.c pkcs15-cache.c pkcs15-syn.c \
|
||||
pkcs15-gemsafeV1.c \
|
||||
pkcs15-algo.c pkcs15-cache.c pkcs15-syn.c \
|
||||
\
|
||||
muscle.c muscle-filesystem.c \
|
||||
\
|
||||
|
@ -45,7 +44,7 @@ libopensc_la_SOURCES = \
|
|||
pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \
|
||||
pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \
|
||||
pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c pkcs15-oberthur.c \
|
||||
pkcs15-itacns.c \
|
||||
pkcs15-itacns.c pkcs15-gemsafeV1.c \
|
||||
compression.c p15card-helper.c \
|
||||
libopensc.exports
|
||||
if WIN32
|
||||
|
|
|
@ -7,8 +7,7 @@ OBJECTS = \
|
|||
\
|
||||
pkcs15.obj pkcs15-cert.obj pkcs15-data.obj pkcs15-pin.obj \
|
||||
pkcs15-prkey.obj pkcs15-pubkey.obj pkcs15-sec.obj \
|
||||
pkcs15-wrap.obj pkcs15-algo.obj pkcs15-cache.obj pkcs15-syn.obj \
|
||||
pkcs15-gemsafeV1.obj \
|
||||
pkcs15-algo.obj pkcs15-cache.obj pkcs15-syn.obj \
|
||||
\
|
||||
muscle.obj muscle-filesystem.obj \
|
||||
\
|
||||
|
@ -28,7 +27,7 @@ OBJECTS = \
|
|||
pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-postecert.obj pkcs15-gemsafeGPK.obj \
|
||||
pkcs15-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \
|
||||
pkcs15-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-oberthur.obj \
|
||||
pkcs15-itacns.obj \
|
||||
pkcs15-itacns.obj pkcs15-gemsafeV1.obj \
|
||||
compression.obj p15card-helper.obj \
|
||||
$(TOPDIR)\win32\versioninfo.res
|
||||
|
||||
|
|
|
@ -137,9 +137,7 @@ sc_pkcs15_decipher
|
|||
sc_pkcs15_decode_aodf_entry
|
||||
sc_pkcs15_decode_cdf_entry
|
||||
sc_pkcs15_decode_dodf_entry
|
||||
sc_pkcs15_decode_enveloped_data
|
||||
sc_pkcs15_decode_prkdf_entry
|
||||
sc_pkcs15_decode_prkey
|
||||
sc_pkcs15_decode_pubkey
|
||||
sc_pkcs15_decode_pubkey_dsa
|
||||
sc_pkcs15_decode_pubkey_rsa
|
||||
|
@ -150,10 +148,8 @@ sc_pkcs15_encode_aodf_entry
|
|||
sc_pkcs15_encode_cdf_entry
|
||||
sc_pkcs15_encode_df
|
||||
sc_pkcs15_encode_dodf_entry
|
||||
sc_pkcs15_encode_enveloped_data
|
||||
sc_pkcs15_encode_odf
|
||||
sc_pkcs15_encode_prkdf_entry
|
||||
sc_pkcs15_encode_prkey
|
||||
sc_pkcs15_encode_pubkey
|
||||
sc_pkcs15_encode_pubkey_dsa
|
||||
sc_pkcs15_encode_pubkey_rsa
|
||||
|
@ -162,7 +158,6 @@ sc_pkcs15_encode_pubkey_gostr3410
|
|||
sc_pkcs15_encode_pukdf_entry
|
||||
sc_pkcs15_encode_tokeninfo
|
||||
sc_pkcs15_encode_unusedspace
|
||||
sc_pkcs15_erase_prkey
|
||||
sc_pkcs15_erase_pubkey
|
||||
sc_pkcs15_find_cert_by_id
|
||||
sc_pkcs15_find_data_object_by_app_oid
|
||||
|
@ -205,7 +200,6 @@ sc_pkcs15_read_cached_file
|
|||
sc_pkcs15_read_certificate
|
||||
sc_pkcs15_read_data_object
|
||||
sc_pkcs15_read_file
|
||||
sc_pkcs15_read_prkey
|
||||
sc_pkcs15_read_pubkey
|
||||
sc_pkcs15_pubkey_from_prvkey
|
||||
sc_pkcs15_pubkey_from_cert
|
||||
|
@ -215,9 +209,7 @@ sc_pkcs15_remove_unusedspace
|
|||
sc_pkcs15_search_objects
|
||||
sc_pkcs15_unbind
|
||||
sc_pkcs15_unblock_pin
|
||||
sc_pkcs15_unwrap_data
|
||||
sc_pkcs15_verify_pin
|
||||
sc_pkcs15_wrap_data
|
||||
sc_pkcs15emu_add_data_object
|
||||
sc_pkcs15emu_add_pin_obj
|
||||
sc_pkcs15emu_add_rsa_prkey
|
||||
|
|
|
@ -333,152 +333,7 @@ int sc_pkcs15_encode_prkdf_entry(sc_context_t *ctx,
|
|||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store private keys on the card, encrypted
|
||||
*/
|
||||
static const struct sc_asn1_entry c_asn1_dsa_prkey_obj[] = {
|
||||
{ "privateKey", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC, NULL, NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static int
|
||||
sc_pkcs15_encode_prkey_dsa(sc_context_t *ctx,
|
||||
struct sc_pkcs15_prkey_dsa *key,
|
||||
u8 **buf, size_t *buflen)
|
||||
{
|
||||
struct sc_asn1_entry asn1_dsa_prkey_obj[2];
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_dsa_prkey_obj, asn1_dsa_prkey_obj);
|
||||
sc_format_asn1_entry(asn1_dsa_prkey_obj + 0,
|
||||
key->priv.data, &key->priv.len, 1);
|
||||
|
||||
return sc_asn1_encode(ctx, asn1_dsa_prkey_obj, buf, buflen);
|
||||
}
|
||||
|
||||
static int
|
||||
sc_pkcs15_decode_prkey_dsa(sc_context_t *ctx,
|
||||
struct sc_pkcs15_prkey_dsa *key,
|
||||
const u8 *buf, size_t buflen)
|
||||
{
|
||||
struct sc_asn1_entry asn1_dsa_prkey_obj[2];
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_dsa_prkey_obj, asn1_dsa_prkey_obj);
|
||||
sc_format_asn1_entry(asn1_dsa_prkey_obj + 0,
|
||||
&key->priv.data, &key->priv.len, 0);
|
||||
|
||||
return sc_asn1_decode(ctx, asn1_dsa_prkey_obj, buf, buflen, NULL, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
sc_pkcs15_encode_prkey(sc_context_t *ctx,
|
||||
struct sc_pkcs15_prkey *key,
|
||||
u8 **buf, size_t *len)
|
||||
{
|
||||
if (key->algorithm == SC_ALGORITHM_DSA)
|
||||
return sc_pkcs15_encode_prkey_dsa(ctx, &key->u.dsa, buf, len);
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Cannot encode private key type %u.",
|
||||
key->algorithm);
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
sc_pkcs15_decode_prkey(sc_context_t *ctx,
|
||||
struct sc_pkcs15_prkey *key,
|
||||
const u8 *buf, size_t len)
|
||||
{
|
||||
if (key->algorithm == SC_ALGORITHM_DSA)
|
||||
return sc_pkcs15_decode_prkey_dsa(ctx, &key->u.dsa, buf, len);
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Cannot decode private key type %u.",
|
||||
key->algorithm);
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
sc_pkcs15_read_prkey(struct sc_pkcs15_card *p15card,
|
||||
const struct sc_pkcs15_object *obj,
|
||||
const char *passphrase,
|
||||
struct sc_pkcs15_prkey **out)
|
||||
{
|
||||
sc_context_t *ctx = p15card->card->ctx;
|
||||
struct sc_pkcs15_prkey_info *info;
|
||||
struct sc_pkcs15_prkey key;
|
||||
sc_path_t path;
|
||||
u8 *data = NULL;
|
||||
size_t len;
|
||||
int r;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
switch (obj->type) {
|
||||
case SC_PKCS15_TYPE_PRKEY_RSA:
|
||||
key.algorithm = SC_ALGORITHM_RSA;
|
||||
break;
|
||||
case SC_PKCS15_TYPE_PRKEY_DSA:
|
||||
key.algorithm = SC_ALGORITHM_DSA;
|
||||
break;
|
||||
default:
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unsupported object type.");
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
info = (struct sc_pkcs15_prkey_info *) obj->data;
|
||||
if (info->native) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Private key is native, will not read.");
|
||||
return SC_ERROR_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
path = info->path;
|
||||
if (path.type == SC_PATH_TYPE_PATH_PROT)
|
||||
path.type = SC_PATH_TYPE_PATH;
|
||||
|
||||
r = sc_pkcs15_read_file(p15card, &path, &data, &len, NULL);
|
||||
if (r < 0) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unable to read private key file.");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Is this a protected file? */
|
||||
if (info->path.type == SC_PATH_TYPE_PATH_PROT) {
|
||||
u8 *clear;
|
||||
size_t clear_len;
|
||||
|
||||
if (passphrase == NULL) {
|
||||
r = SC_ERROR_PASSPHRASE_REQUIRED;
|
||||
goto fail;
|
||||
}
|
||||
r = sc_pkcs15_unwrap_data(ctx,
|
||||
passphrase,
|
||||
data, len,
|
||||
&clear, &clear_len);
|
||||
if (r < 0) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Failed to unwrap privat key.");
|
||||
goto fail;
|
||||
}
|
||||
free(data);
|
||||
data = clear;
|
||||
len = clear_len;
|
||||
}
|
||||
|
||||
r = sc_pkcs15_decode_prkey(ctx, &key, data, len);
|
||||
if (r < 0) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unable to decode private key");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*out = malloc(sizeof(key));
|
||||
if (*out == NULL) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
**out = key;
|
||||
free(data);
|
||||
return 0;
|
||||
|
||||
fail: if (data)
|
||||
free(data);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *key)
|
||||
{
|
||||
assert(key != NULL);
|
||||
|
|
|
@ -1,407 +0,0 @@
|
|||
/*
|
||||
* pkcs15.c: PKCS #15 wrap/unwrap functions
|
||||
*
|
||||
* Copyright (C) 2002 Olaf Kirch <okir@lst.de>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef ENABLE_OPENSSL
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* The asn.1 stuff from openssl and the one from opensc don't
|
||||
* coexist very well. Openssl has typedef ... ASN1_OBJECT; while
|
||||
* in opensc has a #define ASN1_OBJECT 6.
|
||||
*
|
||||
* Everything seems to work fine however if the openssl one is included
|
||||
* first.
|
||||
*/
|
||||
#include "internal.h"
|
||||
#include "asn1.h"
|
||||
#include "pkcs15.h"
|
||||
|
||||
|
||||
#ifndef ENABLE_OPENSSL
|
||||
int
|
||||
sc_pkcs15_wrap_data(sc_context_t *ctx,
|
||||
const char *passphrase,
|
||||
const u8 *in, size_t in_len,
|
||||
u8 **out, size_t *out_len)
|
||||
{
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
sc_pkcs15_unwrap_data(sc_context_t *ctx,
|
||||
const char *passphrase,
|
||||
const u8 *in, size_t in_len,
|
||||
u8 **out, size_t *out_len)
|
||||
{
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
#else /* ENABLE_OPENSSL */
|
||||
|
||||
static int
|
||||
sc_pkcs15_derive_key(sc_context_t *ctx,
|
||||
const struct sc_algorithm_id *der_alg,
|
||||
const struct sc_algorithm_id *enc_alg,
|
||||
const char *passphrase,
|
||||
EVP_CIPHER_CTX *crypt_ctx, int enc_dec)
|
||||
{
|
||||
struct sc_pbkdf2_params *info;
|
||||
unsigned int key_len;
|
||||
const EVP_CIPHER *cipher;
|
||||
u8 *iv = NULL, key[64];
|
||||
int r;
|
||||
|
||||
if (!ctx || ! der_alg || !enc_alg)
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
|
||||
/* XXX: We might also encounter PBES2 here */
|
||||
if (der_alg->algorithm != SC_ALGORITHM_PBKDF2) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unsupported key derivation algorithm.\n");
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
switch (enc_alg->algorithm) {
|
||||
case SC_ALGORITHM_3DES:
|
||||
cipher = EVP_des_ede3_cbc();
|
||||
iv = (u8 *) enc_alg->params;
|
||||
break;
|
||||
case SC_ALGORITHM_DES:
|
||||
cipher = EVP_des_cbc();
|
||||
iv = (u8 *) enc_alg->params;
|
||||
break;
|
||||
default:
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unsupported key encryption algorithm.\n");
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!iv) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unsupported key encryption parameters.\n");
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
key_len = EVP_CIPHER_key_length(cipher);
|
||||
|
||||
info = (struct sc_pbkdf2_params *) der_alg->params;
|
||||
if (!info) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Key parameters missing.\n");
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
if (info->key_length && info->key_length != key_len) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Incompatible key length.\n");
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
if (key_len > sizeof(key)) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Huge key length (%u).\n", key_len);
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
r = PKCS5_PBKDF2_HMAC_SHA1(passphrase, -1,
|
||||
info->salt, info->salt_len,
|
||||
info->iterations, key_len, key);
|
||||
if (r == 0) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Key derivation failed.\n");
|
||||
return SC_ERROR_INTERNAL; /* for lack of something better */
|
||||
}
|
||||
|
||||
/* Now we have the key. Set up the cipher context */
|
||||
memset(crypt_ctx, 0, sizeof(*crypt_ctx));
|
||||
EVP_CipherInit(crypt_ctx, cipher, key, iv, enc_dec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_cipher(EVP_CIPHER_CTX *cipher_ctx, const u8 *in, size_t in_len,
|
||||
u8 **out, size_t *out_len)
|
||||
{
|
||||
const u8 *end;
|
||||
u8 *p;
|
||||
size_t bl, left, total;
|
||||
int done;
|
||||
|
||||
*out = p = malloc(in_len + EVP_CIPHER_CTX_key_length(cipher_ctx));
|
||||
*out_len = total = 0;
|
||||
|
||||
bl = EVP_CIPHER_CTX_block_size(cipher_ctx);
|
||||
end = in + in_len;
|
||||
while (in < end) {
|
||||
if ((left = end - in) > bl)
|
||||
left = bl;
|
||||
if (!EVP_CipherUpdate(cipher_ctx,
|
||||
p + total, &done,
|
||||
(u8 *) in, (int)left))
|
||||
goto fail;
|
||||
total += done;
|
||||
in += left;
|
||||
}
|
||||
if (1 || total < in_len) {
|
||||
if (!EVP_CipherFinal(cipher_ctx, p + total, &done))
|
||||
goto fail;
|
||||
total += done;
|
||||
}
|
||||
*out_len = total;
|
||||
return 0;
|
||||
|
||||
fail: free(p);
|
||||
return SC_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
int
|
||||
sc_pkcs15_wrap_data(sc_context_t *ctx,
|
||||
const char *passphrase,
|
||||
const u8 *in, size_t in_len,
|
||||
u8 **out, size_t *out_len)
|
||||
{
|
||||
struct sc_pkcs15_enveloped_data envdata;
|
||||
EVP_CIPHER_CTX cipher_ctx;
|
||||
struct sc_pbkdf2_params der_info;
|
||||
u8 des_iv[8];
|
||||
int r;
|
||||
|
||||
memset(&envdata, 0, sizeof(envdata));
|
||||
memset(&der_info, 0, sizeof(der_info));
|
||||
|
||||
RAND_bytes(des_iv, sizeof(des_iv));
|
||||
der_info.salt_len = sizeof(der_info.salt);
|
||||
RAND_bytes(der_info.salt, sizeof(der_info.salt));
|
||||
der_info.iterations = 32;
|
||||
der_info.hash_alg.algorithm = SC_ALGORITHM_SHA1;
|
||||
envdata.id.len = 1;
|
||||
envdata.ke_alg.algorithm = SC_ALGORITHM_PBKDF2;
|
||||
envdata.ke_alg.params = &der_info;
|
||||
envdata.ce_alg.algorithm = SC_ALGORITHM_3DES;
|
||||
envdata.ce_alg.params = des_iv;
|
||||
envdata.key = (u8 *) "";
|
||||
r = sc_pkcs15_derive_key(ctx, &envdata.ke_alg, &envdata.ce_alg,
|
||||
passphrase, &cipher_ctx, 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Now encrypt the data using the derived key */
|
||||
r = do_cipher(&cipher_ctx, in, in_len,
|
||||
&envdata.content, &envdata.content_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Finally, DER encode the whole mess */
|
||||
r = sc_pkcs15_encode_enveloped_data(ctx, &envdata, out, out_len);
|
||||
|
||||
free(envdata.content);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sc_pkcs15_unwrap_data(sc_context_t *ctx,
|
||||
const char *passphrase,
|
||||
const u8 *in, size_t in_len,
|
||||
u8 **out, size_t *out_len)
|
||||
{
|
||||
struct sc_pkcs15_enveloped_data envdata;
|
||||
EVP_CIPHER_CTX cipher_ctx;
|
||||
int r;
|
||||
|
||||
memset(&envdata, 0, sizeof(envdata));
|
||||
r = sc_pkcs15_decode_enveloped_data(ctx, &envdata, in, in_len);
|
||||
if (r < 0) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Failed to decode EnvelopedData.\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Derive the key using the info in EnvelopedData */
|
||||
r = sc_pkcs15_derive_key(ctx, &envdata.ke_alg, &envdata.ce_alg,
|
||||
passphrase, &cipher_ctx, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Now decrypt the data using the derived key */
|
||||
r = do_cipher(&cipher_ctx, envdata.content, envdata.content_len,
|
||||
out, out_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (envdata.ce_alg.params)
|
||||
free(envdata.ce_alg.params);
|
||||
if (envdata.ke_alg.params)
|
||||
free(envdata.ke_alg.params);
|
||||
free(envdata.content);
|
||||
return r;
|
||||
}
|
||||
#endif /* ENABLE_OPENSSL */
|
||||
|
||||
/*
|
||||
* Encode/decode EnvelopedData
|
||||
* Note we cheat with the recipientInfo field, which is a SET OF:
|
||||
* we treat it as if there's always just one element in the set.
|
||||
*/
|
||||
static const struct sc_asn1_entry c_asn1_enveloped_data_attr[] = {
|
||||
{ "version", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
|
||||
{ "originator", SC_ASN1_STRUCT, SC_ASN1_CONS| SC_ASN1_TAG_SEQUENCE, SC_ASN1_OPTIONAL, NULL, NULL },
|
||||
{ "recipients", SC_ASN1_STRUCT, SC_ASN1_CONS| SC_ASN1_TAG_SET, 0, NULL, NULL },
|
||||
{ "contentInfo",SC_ASN1_STRUCT, SC_ASN1_CONS| SC_ASN1_TAG_SEQUENCE, 0, NULL, NULL },
|
||||
/* some more optional foo we ignore for now */
|
||||
{ NULL, 0, 0, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_content_attr[] = {
|
||||
{ "contentType",SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, NULL, NULL },
|
||||
{ "contentEncrAlg", SC_ASN1_ALGORITHM_ID, SC_ASN1_CONS| SC_ASN1_TAG_SEQUENCE, 0, NULL, NULL },
|
||||
{ "encrContent",SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_encr_content[] = {
|
||||
{ "data", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_recipients_attr[] = {
|
||||
{ "kekri", SC_ASN1_STRUCT, SC_ASN1_CTX | 2 | SC_ASN1_CONS , 0, NULL, NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_kekri_attr[] = {
|
||||
{ "version", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
|
||||
{ "id", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_TAG_SEQUENCE, 0, NULL, NULL },
|
||||
{ "keyEncrAlg", SC_ASN1_ALGORITHM_ID, SC_ASN1_CONS | SC_ASN1_TAG_SEQUENCE, 0, NULL, NULL },
|
||||
{ "keyEncrKey", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_kek_attr[] = {
|
||||
{ "id", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL },
|
||||
{ "date", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_GENERALIZEDTIME, SC_ASN1_OPTIONAL, NULL, NULL },
|
||||
{ "other", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_TAG_SEQUENCE, SC_ASN1_OPTIONAL, NULL, NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
int
|
||||
sc_pkcs15_decode_enveloped_data(sc_context_t *ctx,
|
||||
struct sc_pkcs15_enveloped_data *result,
|
||||
const u8 *buf, size_t buflen)
|
||||
{
|
||||
struct sc_asn1_entry asn1_enveloped_data_attr[5],
|
||||
asn1_content_attr[4],
|
||||
asn1_encr_content[2],
|
||||
asn1_recipients_attr[2],
|
||||
asn1_kekri_attr[5],
|
||||
asn1_kek_attr[4];
|
||||
struct sc_pkcs15_enveloped_data data;
|
||||
int r;
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_enveloped_data_attr, asn1_enveloped_data_attr);
|
||||
sc_copy_asn1_entry(c_asn1_content_attr, asn1_content_attr);
|
||||
sc_copy_asn1_entry(c_asn1_encr_content, asn1_encr_content);
|
||||
sc_copy_asn1_entry(c_asn1_recipients_attr, asn1_recipients_attr);
|
||||
sc_copy_asn1_entry(c_asn1_kekri_attr, asn1_kekri_attr);
|
||||
sc_copy_asn1_entry(c_asn1_kek_attr, asn1_kek_attr);
|
||||
|
||||
sc_format_asn1_entry(asn1_enveloped_data_attr + 2,
|
||||
asn1_recipients_attr, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_enveloped_data_attr + 3,
|
||||
asn1_content_attr, NULL, 0);
|
||||
|
||||
sc_format_asn1_entry(asn1_content_attr + 1, &data.ce_alg, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_content_attr + 2,
|
||||
asn1_encr_content, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_encr_content + 0,
|
||||
&data.content, &data.content_len, 0);
|
||||
|
||||
sc_format_asn1_entry(asn1_recipients_attr + 0,
|
||||
asn1_kekri_attr, NULL, 0);
|
||||
|
||||
sc_format_asn1_entry(asn1_kekri_attr + 1,
|
||||
asn1_kek_attr, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_kekri_attr + 2,
|
||||
&data.ke_alg, NULL, 0);
|
||||
sc_format_asn1_entry(asn1_kekri_attr + 3,
|
||||
&data.key, &data.key_len, 0);
|
||||
|
||||
sc_format_asn1_entry(asn1_kek_attr + 0,
|
||||
&data.id, &data.id.len, 0);
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
r = sc_asn1_decode(ctx, asn1_enveloped_data_attr, buf, buflen, NULL, NULL);
|
||||
if (r >= 0)
|
||||
*result = data;
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
sc_pkcs15_encode_enveloped_data(sc_context_t *ctx,
|
||||
struct sc_pkcs15_enveloped_data *data,
|
||||
u8 **buf, size_t *buflen)
|
||||
{
|
||||
static struct sc_object_id oid_id_data = {{ 1, 2, 840, 113549, 1, 7, 1, -1 }};
|
||||
struct sc_asn1_entry asn1_enveloped_data_attr[5],
|
||||
asn1_content_attr[4],
|
||||
asn1_encr_content[2],
|
||||
asn1_recipients_attr[2],
|
||||
asn1_kekri_attr[5],
|
||||
asn1_kek_attr[4];
|
||||
int version2 = 2, version4 = 4, r;
|
||||
|
||||
sc_copy_asn1_entry(c_asn1_enveloped_data_attr, asn1_enveloped_data_attr);
|
||||
sc_copy_asn1_entry(c_asn1_content_attr, asn1_content_attr);
|
||||
sc_copy_asn1_entry(c_asn1_encr_content, asn1_encr_content);
|
||||
sc_copy_asn1_entry(c_asn1_recipients_attr, asn1_recipients_attr);
|
||||
sc_copy_asn1_entry(c_asn1_kekri_attr, asn1_kekri_attr);
|
||||
sc_copy_asn1_entry(c_asn1_kek_attr, asn1_kek_attr);
|
||||
|
||||
sc_format_asn1_entry(asn1_enveloped_data_attr + 0,
|
||||
&version2, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_enveloped_data_attr + 2,
|
||||
asn1_recipients_attr, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_enveloped_data_attr + 3,
|
||||
asn1_content_attr, NULL, 1);
|
||||
|
||||
sc_format_asn1_entry(asn1_content_attr + 0, &oid_id_data, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_content_attr + 1, &data->ce_alg, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_content_attr + 2,
|
||||
asn1_encr_content, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_encr_content + 0,
|
||||
data->content, &data->content_len, 1);
|
||||
|
||||
sc_format_asn1_entry(asn1_recipients_attr + 0,
|
||||
asn1_kekri_attr, NULL, 1);
|
||||
|
||||
sc_format_asn1_entry(asn1_kekri_attr + 0,
|
||||
&version4, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_kekri_attr + 1,
|
||||
asn1_kek_attr, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_kekri_attr + 2,
|
||||
&data->ke_alg, NULL, 1);
|
||||
sc_format_asn1_entry(asn1_kekri_attr + 3,
|
||||
data->key, &data->key_len, 1);
|
||||
|
||||
sc_format_asn1_entry(asn1_kek_attr + 0,
|
||||
&data->id, &data->id.len, 1);
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
r = sc_asn1_encode(ctx, asn1_enveloped_data_attr, buf, buflen);
|
||||
return r;
|
||||
}
|
|
@ -584,17 +584,9 @@ int sc_pkcs15_pubkey_from_spki_filename(struct sc_context *,
|
|||
char *, sc_pkcs15_pubkey_t ** );
|
||||
int sc_pkcs15_pubkey_from_spki(struct sc_context *,
|
||||
sc_pkcs15_pubkey_t **, u8 *, size_t, int);
|
||||
int sc_pkcs15_read_prkey(struct sc_pkcs15_card *,
|
||||
const struct sc_pkcs15_object *,
|
||||
const char *passphrase,
|
||||
struct sc_pkcs15_prkey **);
|
||||
int sc_pkcs15_decode_prkey(struct sc_context *,
|
||||
struct sc_pkcs15_prkey *,
|
||||
const u8 *, size_t);
|
||||
int sc_pkcs15_encode_prkey(struct sc_context *,
|
||||
struct sc_pkcs15_prkey *,
|
||||
u8 **, size_t *);
|
||||
void sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *prkey);
|
||||
void sc_pkcs15_free_prkey(struct sc_pkcs15_prkey *prkey);
|
||||
void sc_pkcs15_free_key_params(struct sc_pkcs15_key_params *params);
|
||||
|
||||
|
@ -756,16 +748,6 @@ void sc_pkcs15_free_data_info(sc_pkcs15_data_info_t *data);
|
|||
void sc_pkcs15_free_pin_info(sc_pkcs15_pin_info_t *pin);
|
||||
void sc_pkcs15_free_object(sc_pkcs15_object_t *obj);
|
||||
|
||||
/* File content wrapping */
|
||||
int sc_pkcs15_wrap_data(struct sc_context *ctx,
|
||||
const char *passphrase,
|
||||
const u8 *in, size_t in_len,
|
||||
u8 **out, size_t *out_len);
|
||||
int sc_pkcs15_unwrap_data(struct sc_context *ctx,
|
||||
const char *passphrase,
|
||||
const u8 *in, size_t in_len,
|
||||
u8 **out, size_t *out_len);
|
||||
|
||||
/* Generic file i/o */
|
||||
int sc_pkcs15_read_file(struct sc_pkcs15_card *p15card,
|
||||
const struct sc_path *path,
|
||||
|
|
|
@ -212,9 +212,6 @@ struct sc_pkcs15init_prkeyargs {
|
|||
} params;
|
||||
|
||||
struct sc_pkcs15_prkey key;
|
||||
|
||||
/* support for non-native keys */
|
||||
char * passphrase;
|
||||
};
|
||||
|
||||
struct sc_pkcs15init_keygen_args {
|
||||
|
@ -222,8 +219,6 @@ struct sc_pkcs15init_keygen_args {
|
|||
const char * pubkey_label;
|
||||
};
|
||||
|
||||
#define SC_PKCS15INIT_NO_PASSPHRASE 0x0002
|
||||
|
||||
struct sc_pkcs15init_pubkeyargs {
|
||||
struct sc_pkcs15_id id;
|
||||
struct sc_pkcs15_id auth_id;
|
||||
|
|
|
@ -1323,9 +1323,6 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card,
|
|||
* the key as extractable. */
|
||||
if (!(keyargs->access_flags & SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE))
|
||||
LOG_TEST_RET(ctx, SC_ERROR_INCOMPATIBLE_KEY, "Card does not support this key.");
|
||||
|
||||
if (!keyargs->passphrase && !(keyargs->flags & SC_PKCS15INIT_NO_PASSPHRASE))
|
||||
LOG_TEST_RET(ctx, SC_ERROR_PASSPHRASE_REQUIRED, "No key encryption passphrase given.");
|
||||
}
|
||||
|
||||
/* Select a intrinsic Key ID if user didn't specify one */
|
||||
|
@ -1349,42 +1346,12 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card,
|
|||
|
||||
/* Get the number of private keys already on this card */
|
||||
idx = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, NULL, 0);
|
||||
if (!(keyargs->access_flags & SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE)) {
|
||||
r = profile->ops->create_key(profile, p15card, object);
|
||||
LOG_TEST_RET(ctx, r, "Card specific 'create key' failed");
|
||||
|
||||
r = profile->ops->store_key(profile, p15card, object, &key);
|
||||
LOG_TEST_RET(ctx, r, "Card specific 'store key' failed");
|
||||
} else {
|
||||
struct sc_pkcs15_der encoded, wrapped, *der = &encoded;
|
||||
r = profile->ops->create_key(profile, p15card, object);
|
||||
LOG_TEST_RET(ctx, r, "Card specific 'create key' failed");
|
||||
|
||||
/* DER encode the private key */
|
||||
encoded.value = wrapped.value = NULL;
|
||||
r = sc_pkcs15_encode_prkey(ctx, &key, &encoded.value, &encoded.len);
|
||||
LOG_TEST_RET(ctx, r, "Failed to encode private key");
|
||||
|
||||
if (keyargs->passphrase) {
|
||||
r = sc_pkcs15_wrap_data(ctx, keyargs->passphrase, der->value, der->len,
|
||||
&wrapped.value, &wrapped.len);
|
||||
if (r < 0) {
|
||||
free(der->value);
|
||||
LOG_TEST_RET(ctx, r, "Failed to wrap private key data");
|
||||
}
|
||||
der = &wrapped;
|
||||
}
|
||||
|
||||
r = sc_pkcs15init_store_data(p15card, profile, object, der, &key_info->path);
|
||||
|
||||
/* If the key is encrypted, flag the PrKDF entry as
|
||||
* indirect-protected */
|
||||
if (keyargs->passphrase)
|
||||
key_info->path.type = SC_PATH_TYPE_PATH_PROT;
|
||||
|
||||
free(encoded.value);
|
||||
free(wrapped.value);
|
||||
|
||||
LOG_TEST_RET(ctx, r, "Failed to store private key data");
|
||||
}
|
||||
r = profile->ops->store_key(profile, p15card, object, &key);
|
||||
LOG_TEST_RET(ctx, r, "Card specific 'store key' failed");
|
||||
|
||||
/* Now update the PrKDF */
|
||||
r = sc_pkcs15init_add_object(p15card, profile, SC_PKCS15_PRKDF, object);
|
||||
|
@ -1894,8 +1861,7 @@ check_keygen_params_consistency(struct sc_card *card, struct sc_pkcs15init_keyge
|
|||
* 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)
|
||||
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;
|
||||
|
|
|
@ -121,7 +121,7 @@ enum {
|
|||
OPT_PASSPHRASE,
|
||||
OPT_PUBKEY,
|
||||
OPT_EXTRACTABLE,
|
||||
OPT_UNPROTECTED,
|
||||
OPT_INSECURE,
|
||||
OPT_AUTHORITY,
|
||||
OPT_ASSERT_PRISTINE,
|
||||
OPT_SECRET,
|
||||
|
@ -184,7 +184,7 @@ const struct option options[] = {
|
|||
{ "finalize", no_argument, NULL, 'F' },
|
||||
|
||||
{ "extractable", no_argument, NULL, OPT_EXTRACTABLE },
|
||||
{ "insecure", no_argument, NULL, OPT_UNPROTECTED },
|
||||
{ "insecure", no_argument, NULL, OPT_INSECURE },
|
||||
{ "use-default-transport-keys",
|
||||
no_argument, NULL, 'T' },
|
||||
{ "no-prompt", no_argument, NULL, OPT_NO_PROMPT },
|
||||
|
@ -241,7 +241,7 @@ static const char * option_help[] = {
|
|||
"Finish initialization phase of the smart card",
|
||||
|
||||
"Private key stored as an extractable key",
|
||||
"Insecure mode: do not require PIN/passphrase for private key",
|
||||
"Insecure mode: do not require a PIN for private key",
|
||||
"Do not ask for transport keys if the driver thinks it knows the key",
|
||||
"Do not prompt the user; if no PINs supplied, pinpad will be used",
|
||||
|
||||
|
@ -316,7 +316,7 @@ static struct sc_pkcs15_card * p15card = NULL;
|
|||
static char * opt_reader = NULL;
|
||||
static unsigned int opt_actions;
|
||||
static int opt_extractable = 0,
|
||||
opt_unprotected = 0,
|
||||
opt_insecure = 0,
|
||||
opt_authority = 0,
|
||||
opt_no_prompt = 0,
|
||||
opt_no_sopin = 0,
|
||||
|
@ -1493,25 +1493,13 @@ static int init_keyargs(struct sc_pkcs15init_prkeyargs *args)
|
|||
sc_pkcs15_format_id(opt_objectid, &args->id);
|
||||
if (opt_authid) {
|
||||
sc_pkcs15_format_id(opt_authid, &args->auth_id);
|
||||
} else if (!opt_unprotected) {
|
||||
} else if (!opt_insecure) {
|
||||
util_error("no PIN given for key - either use --insecure or \n"
|
||||
"specify a PIN using --auth-id");
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
if (opt_extractable) {
|
||||
args->access_flags |= SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE;
|
||||
if (opt_passphrase) {
|
||||
args->passphrase = opt_passphrase;
|
||||
} else {
|
||||
if (!opt_unprotected) {
|
||||
util_error("no pass phrase given for key - "
|
||||
"either use --insecure or\n"
|
||||
"specify a pass phrase using "
|
||||
"--passphrase");
|
||||
return SC_ERROR_PASSPHRASE_REQUIRED;
|
||||
}
|
||||
args->flags |= SC_PKCS15INIT_NO_PASSPHRASE;
|
||||
}
|
||||
}
|
||||
args->label = opt_label;
|
||||
args->x509_usage = opt_x509_usage;
|
||||
|
@ -2538,11 +2526,11 @@ handle_option(const struct option *opt)
|
|||
this_action = ACTION_STORE_PUBKEY;
|
||||
opt_infile = optarg;
|
||||
break;
|
||||
case OPT_UNPROTECTED:
|
||||
opt_unprotected++;
|
||||
case OPT_INSECURE:
|
||||
opt_insecure = 1;
|
||||
break;
|
||||
case OPT_EXTRACTABLE:
|
||||
opt_extractable++;
|
||||
opt_extractable = 1;
|
||||
break;
|
||||
case OPT_AUTHORITY:
|
||||
opt_authority = 1;
|
||||
|
|
Loading…
Reference in New Issue