diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-09-05 11:32:30 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-09-05 11:32:30 +0200 |
commit | a0e8e636aad06ad1d3d4f2460ee5a7cdf30c393b (patch) | |
tree | fb390ecba5daa4e3512ab6ac9f914fe29e4590ad | |
parent | 7f4d9adf958f00805e60a353d2779434aca36fe2 (diff) | |
download | kernel-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.h | 23 | ||||
-rw-r--r-- | ncr-key-wrap.c | 89 | ||||
-rw-r--r-- | ncr-sessions.c | 162 |
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; |