summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2010-09-05 11:32:30 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-09-05 11:32:30 +0200
commita0e8e636aad06ad1d3d4f2460ee5a7cdf30c393b (patch)
treefb390ecba5daa4e3512ab6ac9f914fe29e4590ad
parent7f4d9adf958f00805e60a353d2779434aca36fe2 (diff)
downloadkernel-crypto-a0e8e636aad06ad1d3d4f2460ee5a7cdf30c393b.tar.gz
kernel-crypto-a0e8e636aad06ad1d3d4f2460ee5a7cdf30c393b.tar.xz
kernel-crypto-a0e8e636aad06ad1d3d4f2460ee5a7cdf30c393b.zip
Rationalized the key wrapping format. It currently is:
PackedData ::= SEQUENCE { version INTEGER { v1(0) } algorithm OBJECT IDENTIFIER, type INTEGER { secret_key(0), public(1), private(2) }, data OCTET STRING } Unfortunately there are not assigned OIDs for all algorithms we support.
-rw-r--r--ncr-int.h23
-rw-r--r--ncr-key-wrap.c89
-rw-r--r--ncr-sessions.c162
3 files changed, 198 insertions, 76 deletions
diff --git a/ncr-int.h b/ncr-int.h
index 87964b08065..c413f846bb6 100644
--- a/ncr-int.h
+++ b/ncr-int.h
@@ -25,19 +25,33 @@ enum ncr_algorithm {
NCR_ALG_NULL,
NCR_ALG_3DES_CBC,
-
- NCR_ALG_MD5,
+ NCR_ALG_3DES_ECB,
+
+ NCR_ALG_AES_ECB,
+ NCR_ALG_AES_CBC,
+ NCR_ALG_AES_CTR,
+
+ NCR_ALG_CAMELIA_ECB,
+ NCR_ALG_CAMELIA_CBC,
+ NCR_ALG_CAMELIA_CTR,
+
+ NCR_ALG_MD5=60,
NCR_ALG_SHA1,
NCR_ALG_SHA2_224,
NCR_ALG_SHA2_256,
NCR_ALG_SHA2_384,
NCR_ALG_SHA2_512,
- NCR_ALG_RSA,
+ NCR_ALG_RSA=120,
NCR_ALG_DSA,
NCR_ALG_DH,
};
+struct algo_oid_st {
+ oid_st oid;
+ int key_size;
+};
+
struct algo_properties_st {
enum ncr_algorithm algo;
const char *kstr;
@@ -56,6 +70,7 @@ struct algo_properties_st {
* NCR_KEY_TYPE_PUBLIC for a public key algorithm.
*/
ncr_key_type_t key_type;
+ const struct algo_oid_st *oids;
};
struct key_item_st {
@@ -192,6 +207,8 @@ int key_to_storage_data( uint8_t** data, size_t * data_size, const struct key_it
const struct algo_properties_st *_ncr_algo_to_properties(const char *algo);
const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla);
int _ncr_key_get_sec_level(struct key_item_st* item);
+const struct algo_properties_st *_ncr_oid_to_properties(oid_st* oid);
+const oid_st* _ncr_properties_to_oid(const struct algo_properties_st * prop, int key_size);
/* CONFIG_COMPAT handling */
diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c
index 7ea70cfc847..52dca51510c 100644
--- a/ncr-key-wrap.c
+++ b/ncr-key-wrap.c
@@ -831,8 +831,8 @@ fail:
/* Packed data are DER encoded:
* PackedData ::= SEQUENCE {
* version INTEGER { v1(0) }
- * type INTEGER { secret_key(0), rsa_privkey(1), rsa_pubkey(2), dsa_privkey(3), dsa_pubkey(4),
- * dh_privkey(5), dh_pubkey(6) },
+ * algorithm OBJECT IDENTIFIER,
+ * type INTEGER { secret_key(0), public(1), private(2) },
* data OCTET STRING
* }
*
@@ -847,6 +847,7 @@ static int key_to_packed_data( uint8_t** sdata, size_t * sdata_size, const struc
unsigned long version = KEY_WRAP_VERSION;
unsigned long type;
unsigned long derlen;
+ const oid_st* oid;
*sdata_size = KEY_DATA_MAX_SIZE;
pkey = kmalloc(*sdata_size, GFP_KERNEL);
@@ -875,37 +876,25 @@ static int key_to_packed_data( uint8_t** sdata, size_t * sdata_size, const struc
goto fail;
}
- switch (key->algorithm->algo) {
- case NCR_ALG_RSA:
- if (key->type == NCR_KEY_TYPE_PUBLIC)
- type = 2;
- else type = 1;
- break;
- case NCR_ALG_DSA:
- if (key->type == NCR_KEY_TYPE_PUBLIC)
- type = 4;
- else type = 3;
- break;
- case NCR_ALG_DH:
- if (key->type == NCR_KEY_TYPE_PUBLIC)
- type = 6;
- else type = 5;
- break;
- default:
- /* unsupported yet */
- ret = -EINVAL;
- err();
- goto fail;
- }
-
+ if (key->type == NCR_KEY_TYPE_PUBLIC)
+ type = 1;
+ else type = 2;
} else {
err();
ret = -EINVAL;
goto fail;
}
+
+ oid = _ncr_properties_to_oid(key->algorithm, pkey_size);
+ if (oid == NULL) {
+ err();
+ ret = -EOPNOTSUPP;
+ goto fail;
+ }
err = der_encode_sequence_multi(derkey, &derlen,
LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+ LTC_ASN1_OBJECT_IDENTIFIER, oid->OIDlen, oid->OID,
LTC_ASN1_SHORT_INTEGER, 1UL, &type,
LTC_ASN1_OCTET_STRING, (unsigned long)pkey_size, pkey,
LTC_ASN1_EOL, 0UL, NULL);
@@ -934,42 +923,17 @@ inline static int packed_type_to_key_type(unsigned long type, struct key_item_st
switch(type) {
case 0:
key->type = NCR_KEY_TYPE_SECRET;
- key->algorithm = _ncr_algo_to_properties("cbc(aes)");
break;
case 1:
- key->type = NCR_KEY_TYPE_PRIVATE;
- key->algorithm = _ncr_algo_to_properties("rsa");
- break;
- case 2:
key->type = NCR_KEY_TYPE_PUBLIC;
- key->algorithm = _ncr_algo_to_properties("rsa");
break;
- case 3:
- key->type = NCR_KEY_TYPE_PRIVATE;
- key->algorithm = _ncr_algo_to_properties("dsa");
- break;
- case 4:
- key->type = NCR_KEY_TYPE_PUBLIC;
- key->algorithm = _ncr_algo_to_properties("dsa");
- break;
- case 5:
+ case 2:
key->type = NCR_KEY_TYPE_PRIVATE;
- key->algorithm = _ncr_algo_to_properties("dh");
- break;
- case 6:
- key->type = NCR_KEY_TYPE_PUBLIC;
- key->algorithm = _ncr_algo_to_properties("dh");
break;
default:
err();
return -EINVAL;
}
-
- if (key->algorithm == NULL) {
- err();
- return -EINVAL;
- }
-
return 0;
}
@@ -981,9 +945,10 @@ static int key_from_packed_data(struct nlattr *tb[], struct key_item_st *key,
const void *data, size_t data_size)
{
ltc_asn1_list list[6];
- int ret, i = 0, pkey_size, err;
+ int ret, i, pkey_size, err;
unsigned long version, type;
uint8_t * pkey = NULL;
+ oid_st oid;
if (data_size > DER_KEY_MAX_SIZE) {
err();
@@ -997,10 +962,16 @@ static int key_from_packed_data(struct nlattr *tb[], struct key_item_st *key,
return -ENOMEM;
}
+ i = 0;
+
list[i].type = LTC_ASN1_SHORT_INTEGER;
list[i].size = 1;
list[i++].data = &version;
+ list[i].type = LTC_ASN1_OBJECT_IDENTIFIER;
+ list[i].size = sizeof(oid.OID)/sizeof(oid.OID[0]);
+ list[i++].data = oid.OID;
+
list[i].type = LTC_ASN1_SHORT_INTEGER;
list[i].size = 1;
list[i++].data = &type;
@@ -1015,14 +986,15 @@ static int key_from_packed_data(struct nlattr *tb[], struct key_item_st *key,
ret = _ncr_tomerr(err);
goto fail;
}
-
+
if (version != KEY_WRAP_VERSION) {
err();
ret = -EINVAL;
goto fail;
}
-
- pkey_size = list[2].size;
+
+ oid.OIDlen = list[1].size;
+ pkey_size = list[3].size;
ret = packed_type_to_key_type(type, key);
if (ret < 0) {
@@ -1030,6 +1002,13 @@ static int key_from_packed_data(struct nlattr *tb[], struct key_item_st *key,
goto fail;
}
+ key->algorithm = _ncr_oid_to_properties(&oid);
+ if (key->algorithm == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
ret = ncr_key_update_flags(key, tb[NCR_ATTR_KEY_FLAGS]);
if (ret != 0) {
err();
diff --git a/ncr-sessions.c b/ncr-sessions.c
index f7e577757a9..a7504b37f21 100644
--- a/ncr-sessions.c
+++ b/ncr-sessions.c
@@ -212,6 +212,89 @@ err_sess:
return NULL;
}
+const oid_st* _ncr_properties_to_oid(const struct algo_properties_st * prop, int key_size)
+{
+int i = 0;
+
+ if (prop->oids == NULL)
+ return NULL;
+
+ do {
+ if (key_size == prop->oids[i].key_size ||
+ prop->oids[i].key_size == -1 /* catch all */) {
+
+ return &prop->oids[i].oid;
+ }
+ } while(prop->oids[++i].key_size != 0);
+
+ return NULL;
+}
+
+const static struct algo_oid_st aes_cbc_oids[] = {
+ {.key_size=16,
+ .oid = {{2,16,840,1,101,3,4,1,2}, 9}},
+ {.key_size=24,
+ .oid = {{2,16,840,1,101,3,4,1,22}, 9}},
+ {.key_size=32,
+ .oid = {{2,16,840,1,101,3,4,1,42}, 9}},
+ {.key_size=0 }
+};
+
+const static struct algo_oid_st aes_ecb_oids[] = {
+ {.key_size=16,
+ .oid = {{2,16,840,1,101,3,4,1,1}, 9}},
+ {.key_size=24,
+ .oid = {{2,16,840,1,101,3,4,1,21}, 9}},
+ {.key_size=32,
+ .oid = {{2,16,840,1,101,3,4,1,41}, 9}},
+ {.key_size=0 }
+};
+
+const static struct algo_oid_st des3_cbc_oids[] = {
+ {.key_size=-1,
+ .oid = {{1,2,840,113549,3,7}, 6}},
+ {.key_size=0 }
+};
+
+/* http://www.oid-info.com/get/1.3.6.1.4.1.4929.1.7
+ */
+const static struct algo_oid_st des3_ecb_oids[] = {
+ {.key_size=-1,
+ .oid = {{1,3,6,1,4,1,4929,1,7}, 9}},
+ {.key_size=0 }
+};
+
+const static struct algo_oid_st camelia_cbc_oids[] = {
+ {.key_size=16,
+ .oid = {{1,2,392,200011,61,1,1,1,2}, 9}},
+ {.key_size=24,
+ .oid = {{1,2,392,200011,61,1,1,1,3}, 9}},
+ {.key_size=32,
+ .oid = {{1,2,392,200011,61,1,1,1,4}, 9}},
+ {.key_size=0 }
+};
+
+const static struct algo_oid_st rsa_oid[] = {
+ {.key_size=-1,
+ .oid = {{1,2,840,113549,1,1,1}, 7}},
+ {.key_size=0 }
+};
+
+const static struct algo_oid_st dsa_oid[] = {
+ {.key_size=-1,
+ .oid = {{1,2,840,10040,4,1}, 6}},
+ {.key_size=0 }
+};
+
+const static struct algo_oid_st dh_oid[] = {
+ {.key_size=-1,
+ .oid = {{1,2,840,10046,2,1}, 6}},
+ {.key_size=0 }
+};
+
+/* OIDs are used in cipher algorithms to distinguish keys on key wrapping.
+ */
+
static const struct algo_properties_st algo_properties[] = {
#define KSTR(x) .kstr = x, .kstr_len = sizeof(x) - 1
{ .algo = NCR_ALG_NULL, KSTR("ecb(cipher_null)"),
@@ -219,25 +302,28 @@ static const struct algo_properties_st algo_properties[] = {
.key_type = NCR_KEY_TYPE_INVALID },
{ .algo = NCR_ALG_3DES_CBC, KSTR("cbc(des3_ede)"),
.needs_iv = 1, .is_symmetric=1, .can_encrypt=1,
- .key_type = NCR_KEY_TYPE_SECRET },
- { KSTR("cbc(aes)"),
+ .key_type = NCR_KEY_TYPE_SECRET, .oids = des3_cbc_oids },
+ { .algo = NCR_ALG_3DES_ECB, KSTR("ecb(des3_ede)"),
+ .needs_iv = 0, .is_symmetric=1, .can_encrypt=1,
+ .key_type = NCR_KEY_TYPE_SECRET, .oids = des3_ecb_oids },
+ { .algo = NCR_ALG_AES_CBC, KSTR("cbc(aes)"),
.needs_iv = 1, .is_symmetric=1, .can_encrypt=1,
- .key_type = NCR_KEY_TYPE_SECRET },
- { KSTR("cbc(camelia)"),
+ .key_type = NCR_KEY_TYPE_SECRET, .oids = aes_cbc_oids },
+ { .algo = NCR_ALG_CAMELIA_CBC, KSTR("cbc(camelia)"),
.needs_iv = 1, .is_symmetric=1, .can_encrypt=1,
- .key_type = NCR_KEY_TYPE_SECRET },
- { KSTR("ctr(aes)"),
+ .key_type = NCR_KEY_TYPE_SECRET, .oids = camelia_cbc_oids },
+ { .algo = NCR_ALG_AES_CTR, KSTR("ctr(aes)"),
.needs_iv = 1, .is_symmetric=1, .can_encrypt=1,
- .key_type = NCR_KEY_TYPE_SECRET },
- { KSTR("ctr(camelia)"),
+ .key_type = NCR_KEY_TYPE_SECRET, /* FIXME: no OIDs */ },
+ { .algo = NCR_ALG_CAMELIA_CTR, KSTR("ctr(camelia)"),
.needs_iv = 1, .is_symmetric=1, .can_encrypt=1,
- .key_type = NCR_KEY_TYPE_SECRET },
- { KSTR("ecb(aes)"),
+ .key_type = NCR_KEY_TYPE_SECRET, /* FIXME: no OIDs */ },
+ { .algo = NCR_ALG_AES_ECB, KSTR("ecb(aes)"),
.needs_iv = 0, .is_symmetric=1, .can_encrypt=1,
- .key_type = NCR_KEY_TYPE_SECRET },
- { KSTR("ecb(camelia)"),
+ .key_type = NCR_KEY_TYPE_SECRET, .oids = aes_ecb_oids },
+ { .algo = NCR_ALG_CAMELIA_ECB, KSTR("ecb(camelia)"),
.needs_iv = 0, .is_symmetric=1, .can_encrypt=1,
- .key_type = NCR_KEY_TYPE_SECRET },
+ .key_type = NCR_KEY_TYPE_SECRET, /* FIXME: no OIDs */ },
{ .algo = NCR_ALG_SHA1, KSTR("sha1"),
.digest_size = 20, .can_digest=1,
.key_type = NCR_KEY_TYPE_INVALID },
@@ -277,17 +363,20 @@ static const struct algo_properties_st algo_properties[] = {
/* NOTE: These algorithm names are not available through the kernel API
(yet). */
{ .algo = NCR_ALG_RSA, KSTR("rsa"), .is_pk = 1,
- .can_encrypt=1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC },
+ .can_encrypt=1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC,
+ .oids = rsa_oid },
{ .algo = NCR_ALG_RSA, KSTR(NCR_ALG_RSA_TRANSPARENT_HASH), .is_pk = 1,
.can_encrypt=1, .can_sign=1, .has_transparent_hash = 1,
- .key_type = NCR_KEY_TYPE_PUBLIC },
+ .key_type = NCR_KEY_TYPE_PUBLIC, /* FIXME: no OIDs */ },
{ .algo = NCR_ALG_DSA, KSTR("dsa"), .is_pk = 1,
- .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC },
+ .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC,
+ .oids = dsa_oid },
{ .algo = NCR_ALG_DSA, KSTR(NCR_ALG_DSA_TRANSPARENT_HASH), .is_pk = 1,
.can_sign=1, .has_transparent_hash = 1,
- .key_type = NCR_KEY_TYPE_PUBLIC },
+ .key_type = NCR_KEY_TYPE_PUBLIC, /* FIXME: no OIDs */ },
{ .algo = NCR_ALG_DH, KSTR("dh"), .is_pk = 1,
- .can_kx=1, .key_type = NCR_KEY_TYPE_PUBLIC },
+ .can_kx=1, .key_type = NCR_KEY_TYPE_PUBLIC,
+ .oids = dh_oid },
#undef KSTR
};
@@ -309,6 +398,43 @@ const struct algo_properties_st *_ncr_algo_to_properties(const char *algo)
return NULL;
}
+static void print_oid(oid_st* oid)
+{
+char txt[128]="";
+char tmp[64];
+int i;
+
+ for (i=0;i<oid->OIDlen;i++) {
+ sprintf(tmp, "%d.", (int)oid->OID[i]);
+ strcat(txt, tmp);
+ }
+
+ dprintk(1, KERN_DEBUG, "unknown oid: %s\n", txt);
+}
+
+const struct algo_properties_st *_ncr_oid_to_properties(oid_st* oid)
+{
+ const struct algo_properties_st *a;
+ int i;
+
+ for (a = algo_properties;
+ a < algo_properties + ARRAY_SIZE(algo_properties); a++) {
+
+ i=0;
+
+ if (a->oids == NULL) continue;
+
+ do {
+ if (a->oids[i].oid.OIDlen == oid->OIDlen &&
+ memcmp(oid->OID, a->oids[i].oid.OID, oid->OIDlen*sizeof(oid->OID[0]))==0)
+ return a;
+ } while(a->oids[++i].key_size != 0);
+ }
+
+ print_oid(oid);
+ return NULL;
+}
+
const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla)
{
const struct algo_properties_st *a;