From 7ceac0e2ae996e219c205d8fd58f3117162261c0 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Tue, 28 Sep 2010 19:21:24 -0400 Subject: [PATCH 018/150] - first pass at enveloped-data decode - first pass at dh-secret-to-key --- src/plugins/preauth/pkinit/pkinit_crypto_nss.c | 124 ++++++++++++++++++++++- 1 files changed, 118 insertions(+), 6 deletions(-) diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index d4c4411..e0696f5 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -1255,7 +1255,7 @@ crypto_cert_select(krb5_context context, pkinit_cert_matching_data *data) CERT_DestroyCertificate(data->ch->id_cryptoctx->cert); } data->ch->id_cryptoctx->cert = cert; - return ENOSYS; + return 0; } /* Try to select the "default" cert. */ @@ -1274,9 +1274,7 @@ crypto_load_cas_and_crls(krb5_context context, pkinit_req_crypto_context req_cryptoctx, pkinit_identity_opts *idopts, pkinit_identity_crypto_context id_cryptoctx, - int idtype, - int catype, - char *id) + int idtype, int catype, char *id) { return ENOSYS; } @@ -1375,7 +1373,59 @@ pkinit_octetstring2key(krb5_context context, unsigned int key_len, krb5_keyblock *krb5key) { - return ENOSYS; + PK11Context *ctx; + unsigned int left, length; + unsigned char c, buf[160 / 8]; /* the longest digest we support */ + char rnd_buf[key_len]; + krb5_data rnd_data; + krb5_error_code result; + SECOidTag hash_alg = SEC_OID_SHA1; + + c = 0; + left = key_len; + while (left > 0) { + ctx = PK11_CreateDigestContext(hash_alg); + if (ctx == NULL) { + memset(buf, 0, sizeof(buf)); + memset(rnd_buf, 0, sizeof(rnd_buf)); + return ENOMEM; + } + if (PK11_DigestBegin(ctx) != SECSuccess) { + memset(buf, 0, sizeof(buf)); + memset(rnd_buf, 0, sizeof(rnd_buf)); + return ENOMEM; + } + if (PK11_DigestOp(ctx, &c, 1) != SECSuccess) { + memset(buf, 0, sizeof(buf)); + memset(rnd_buf, 0, sizeof(rnd_buf)); + return ENOMEM; + } + if (PK11_DigestOp(ctx, key, key_len) != SECSuccess) { + memset(buf, 0, sizeof(buf)); + memset(rnd_buf, 0, sizeof(rnd_buf)); + return ENOMEM; + } + if (PK11_DigestFinal(ctx, buf, &length, + sizeof(buf)) != SECSuccess) { + memset(buf, 0, sizeof(buf)); + memset(rnd_buf, 0, sizeof(rnd_buf)); + return ENOMEM; + } + PK11_DestroyContext(ctx, PR_TRUE); + if (left < length) { + length = left; + } + memcpy(rnd_buf + key_len - left, buf, length); + left -= length; + c++; + } + + rnd_data.data = rnd_buf; + rnd_data.length = key_len; + result = krb5_c_random_to_key(context, etype, &rnd_data, krb5key); + memset(buf, 0, sizeof(buf)); + memset(rnd_buf, 0, sizeof(rnd_buf)); + return result; } static int @@ -1927,7 +1977,69 @@ cms_envelopeddata_verify(krb5_context context, unsigned char **signed_data, unsigned int *signed_data_len) { - return ENOSYS; + NSSCMSMessage *msg; + NSSCMSContentInfo *info; + NSSCMSEnvelopedData *env; + CERTCertDBHandle *certdb; + PLArenaPool *pool; + SECItem *plain, encoded; + + pool = PORT_NewArena(sizeof(double)); + if (pool == NULL) { + return ENOMEM; + } + certdb = CERT_GetDefaultCertDB(); + + /* Decode the message. */ + encoded.data = envel_data; + encoded.len = envel_data_len; + msg = NSS_CMSMessage_CreateFromDER(&encoded, + NULL, NULL, + NULL, NULL, + NULL, NULL); + if (msg == NULL) { + return ENOMEM; + } + + /* Make sure it's enveloped-data. */ + info = NSS_CMSMessage_GetContentInfo(msg); + if (info == NULL) { + NSS_CMSMessage_Destroy(msg); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + if (NSS_CMSContentInfo_GetContentTypeTag(info) != + SEC_OID_PKCS7_ENVELOPED_DATA) { + NSS_CMSMessage_Destroy(msg); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + /* Okay, it's enveloped-data. */ + env = NSS_CMSContentInfo_GetContent(info); + /* FIXME: is that it? We don't have to do anything else? */ + /* FIXME: what do we do about "require_crl_checking"? */ + + /* Pull out the payload. */ + info = NSS_CMSEnvelopedData_GetContentInfo(env); + if (info == NULL) { + NSS_CMSMessage_Destroy(msg); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + plain = NSS_CMSContentInfo_GetContent(info); + + /* Export the payload. */ + if ((plain == NULL) || + (secitem_to_buf_len(plain, signed_data, signed_data_len) != 0)) { + NSS_CMSMessage_Destroy(msg); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + NSS_CMSMessage_Destroy(msg); + PORT_FreeArena(pool, PR_TRUE); + + return 0; } krb5_error_code -- 1.7.6.4