From 22fac738c04644069d3f26c225eb0da09c6ce8db Mon Sep 17 00:00:00 2001
From: Nalin Dahyabhai <nalin@dahyabhai.net>
Date: Thu, 30 Sep 2010 15:12:52 -0400
Subject: [PATCH 031/150] - fix encapsulated content info with a
 might-not-be-supported hack

---
 src/plugins/preauth/pkinit/pkinit_crypto_nss.c |   84 +++++++++++++++++-------
 1 files changed, 61 insertions(+), 23 deletions(-)

diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c
index 84772fc..f66e3ee 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c
@@ -2108,6 +2108,26 @@ cms_contentinfo_create(krb5_context context,
 	NSSCMSContentInfo *info;
 	PLArenaPool *pool;
 	SECItem plain, encoded;
+	SECOidData *encapsulated;
+	SECOidTag encapsulated_tag;
+
+	switch (cms_msg_type) {
+	case CMS_SIGN_DRAFT9:
+		encapsulated_tag = get_pkinit_data_auth_data_tag();
+		break;
+	case CMS_SIGN_CLIENT:
+		encapsulated_tag = get_pkinit_data_auth_data_tag();
+		break;
+	case CMS_SIGN_SERVER:
+		encapsulated_tag = get_pkinit_data_dhkey_data_tag();
+		break;
+	case CMS_ENVEL_SERVER:
+		encapsulated_tag = get_pkinit_data_rkey_data_tag();
+		break;
+	default:
+		return ENOSYS;
+		break;
+	}
 
 	pool = PORT_NewArena(sizeof(double));
 	if (pool == NULL) {
@@ -2126,17 +2146,28 @@ cms_contentinfo_create(krb5_context context,
 		return ENOMEM;
 	}
 
-	plain.data = in_data;
-	plain.len = in_length;
-	if (NSS_CMSContentInfo_SetContent_Data(msg, info, &plain,
+	if (NSS_CMSContentInfo_SetContent_Data(msg, info, NULL,
 					       PR_FALSE) != SECSuccess) {
 		PORT_FreeArena(pool, PR_TRUE);
 		return ENOMEM;
 	}
 
+	encapsulated = SECOID_FindOIDByTag(encapsulated_tag);
+	if (encapsulated == NULL) {
+		pkiDebug("%s: internal error looking up tag %d\n",
+			 __FUNCTION__, encapsulated_tag);
+		PORT_FreeArena(pool, PR_TRUE);
+		return ENOMEM;
+	}
+	info->contentType = encapsulated->oid;
+
+	plain.data = in_data;
+	plain.len = in_length;
 	memset(&encoded, 0, sizeof(encoded));
-	if (NSS_CMSDEREncode(msg, NULL, &encoded, pool) != SECSuccess) {
+	if (NSS_CMSDEREncode(msg, &plain, &encoded, pool) != SECSuccess) {
 		PORT_FreeArena(pool, PR_TRUE);
+		pkiDebug("%s: error encoding data\n",
+			 __FUNCTION__);
 		return ENOMEM;
 	}
 
@@ -2221,8 +2252,6 @@ cms_envelopeddata_create(krb5_context context,
 	}
 
 	/* Set the raw data as the contents for the enveloped-data pointer. */
-	plain.data = key_pack;
-	plain.len = key_pack_len;
 	info = NSS_CMSEnvelopedData_GetContentInfo(env);
 	if (info == NULL) {
 		PORT_FreeArena(pool, PR_TRUE);
@@ -2235,9 +2264,13 @@ cms_envelopeddata_create(krb5_context context,
 	}
 
 	/* Encode and export. */
+	plain.data = key_pack;
+	plain.len = key_pack_len;
 	memset(&encoded, 0, sizeof(encoded));
-	if (NSS_CMSDEREncode(msg, NULL, &encoded, pool) != SECSuccess) {
+	if (NSS_CMSDEREncode(msg, &plain, &encoded, pool) != SECSuccess) {
 		PORT_FreeArena(pool, PR_TRUE);
+		pkiDebug("%s: error encoding enveloped-data\n",
+			 __FUNCTION__);
 		return ENOMEM;
 	}
 	if (secitem_to_buf_len(&encoded, envel_data, envel_data_len) != 0) {
@@ -2349,29 +2382,30 @@ cms_signeddata_create(krb5_context context,
 	NSSCMSSignerInfo *signer;
 	PLArenaPool *pool;
 	SECItem plain, encoded;
-	SECOidTag digest, encapsulated_type_tag;
+	SECOidData *encapsulated;
+	SECOidTag digest, encapsulated_tag;
 	PRBool add_signed_attributes;
 
 	switch (cms_msg_type) {
 	case CMS_SIGN_DRAFT9:
 		digest = SEC_OID_MD5;
 		add_signed_attributes = PR_FALSE;
-		encapsulated_type_tag = get_pkinit_data_auth_data_tag();
+		encapsulated_tag = get_pkinit_data_auth_data_tag();
 		break;
 	case CMS_SIGN_CLIENT:
 		digest = SEC_OID_SHA1;
 		add_signed_attributes = PR_TRUE;
-		encapsulated_type_tag = get_pkinit_data_auth_data_tag();
+		encapsulated_tag = get_pkinit_data_auth_data_tag();
 		break;
 	case CMS_SIGN_SERVER:
 		digest = SEC_OID_SHA1;
 		add_signed_attributes = PR_TRUE;
-		encapsulated_type_tag = get_pkinit_data_dhkey_data_tag();
+		encapsulated_tag = get_pkinit_data_dhkey_data_tag();
 		break;
 	case CMS_ENVEL_SERVER:
 		digest = SEC_OID_SHA1;
 		add_signed_attributes = PR_FALSE;
-		encapsulated_type_tag = get_pkinit_data_rkey_data_tag();
+		encapsulated_tag = get_pkinit_data_rkey_data_tag();
 		break;
 	default:
 		return ENOSYS;
@@ -2379,6 +2413,7 @@ cms_signeddata_create(krb5_context context,
 	}
 
 	if (id_cryptoctx->id_cert == NULL) {
+		pkiDebug("%s: no signer identity\n", __FUNCTION__);
 		return ENOENT;
 	}
 
@@ -2447,27 +2482,30 @@ cms_signeddata_create(krb5_context context,
 		PORT_FreeArena(pool, PR_TRUE);
 		return ENOMEM;
 	}
-	plain.data = payload;
-	plain.len = payload_len;
-#if 0
-	if (NSS_CMSContentInfo_SetContent(msg, info, encapsulated_type_tag,
-					  &plain) != SECSuccess) {
+	if (NSS_CMSContentInfo_SetContent_Data(msg, info, NULL,
+					       PR_FALSE) != SECSuccess) {
 		PORT_FreeArena(pool, PR_TRUE);
 		return ENOMEM;
 	}
-#else
-	if (NSS_CMSContentInfo_SetContent_Data(msg, info, &plain,
-					       PR_FALSE) != SECSuccess) {
+
+	/* Overwrite the OID in the outgoing content with the desired
+	 * encapsulated content type. */
+	encapsulated = SECOID_FindOIDByTag(encapsulated_tag);
+	if (encapsulated == NULL) {
+		pkiDebug("%s: internal error looking up tag %d\n",
+			 __FUNCTION__, encapsulated_tag);
 		PORT_FreeArena(pool, PR_TRUE);
 		return ENOMEM;
 	}
-#endif
+	info->contentType = encapsulated->oid;
 
 	/* Encode and export. */
+	plain.data = payload;
+	plain.len = payload_len;
 	memset(&encoded, 0, sizeof(encoded));
-	if (NSS_CMSDEREncode(msg, NULL, &encoded, pool) != SECSuccess) {
+	if (NSS_CMSDEREncode(msg, &plain, &encoded, pool) != SECSuccess) {
 		PORT_FreeArena(pool, PR_TRUE);
-		pkiDebug("%s: error encoding signed data\n",
+		pkiDebug("%s: error encoding signed-data\n",
 			 __FUNCTION__);
 		return ENOMEM;
 	}
-- 
1.7.6.4

