security/nss/lib/smime/cmsutil.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6  * CMS miscellaneous utility functions.
     7  */
     9 #include "cmslocal.h"
    11 #include "cert.h"
    12 #include "key.h"
    13 #include "secasn1.h"
    14 #include "secitem.h"
    15 #include "secoid.h"
    16 #include "pk11func.h"
    17 #include "secerr.h"
    18 #include "sechash.h"
    20 /*
    21  * NSS_CMSArray_SortByDER - sort array of objects by objects' DER encoding
    22  *
    23  * make sure that the order of the objects guarantees valid DER (which must be
    24  * in lexigraphically ascending order for a SET OF); if reordering is necessary it
    25  * will be done in place (in objs).
    26  */
    27 SECStatus
    28 NSS_CMSArray_SortByDER(void **objs, const SEC_ASN1Template *objtemplate, void **objs2)
    29 {
    30     PLArenaPool *poolp;
    31     int num_objs;
    32     SECItem **enc_objs;
    33     SECStatus rv = SECFailure;
    34     int i;
    36     if (objs == NULL)					/* already sorted */
    37 	return SECSuccess;
    39     num_objs = NSS_CMSArray_Count((void **)objs);
    40     if (num_objs == 0 || num_objs == 1)		/* already sorted. */
    41 	return SECSuccess;
    43     poolp = PORT_NewArena (1024);	/* arena for temporaries */
    44     if (poolp == NULL)
    45 	return SECFailure;		/* no memory; nothing we can do... */
    47     /*
    48      * Allocate arrays to hold the individual encodings which we will use
    49      * for comparisons and the reordered attributes as they are sorted.
    50      */
    51     enc_objs = (SECItem **)PORT_ArenaZAlloc(poolp, (num_objs + 1) * sizeof(SECItem *));
    52     if (enc_objs == NULL)
    53 	goto loser;
    55     /* DER encode each individual object. */
    56     for (i = 0; i < num_objs; i++) {
    57 	enc_objs[i] = SEC_ASN1EncodeItem(poolp, NULL, objs[i], objtemplate);
    58 	if (enc_objs[i] == NULL)
    59 	    goto loser;
    60     }
    61     enc_objs[num_objs] = NULL;
    63     /* now compare and sort objs by the order of enc_objs */
    64     NSS_CMSArray_Sort((void **)enc_objs, NSS_CMSUtil_DERCompare, objs, objs2);
    66     rv = SECSuccess;
    68 loser:
    69     PORT_FreeArena (poolp, PR_FALSE);
    70     return rv;
    71 }
    73 /*
    74  * NSS_CMSUtil_DERCompare - for use with NSS_CMSArray_Sort to
    75  *  sort arrays of SECItems containing DER
    76  */
    77 int
    78 NSS_CMSUtil_DERCompare(void *a, void *b)
    79 {
    80     SECItem *der1 = (SECItem *)a;
    81     SECItem *der2 = (SECItem *)b;
    82     unsigned int j;
    84     /*
    85      * Find the lowest (lexigraphically) encoding.  One that is
    86      * shorter than all the rest is known to be "less" because each
    87      * attribute is of the same type (a SEQUENCE) and so thus the
    88      * first octet of each is the same, and the second octet is
    89      * the length (or the length of the length with the high bit
    90      * set, followed by the length, which also works out to always
    91      * order the shorter first).  Two (or more) that have the
    92      * same length need to be compared byte by byte until a mismatch
    93      * is found.
    94      */
    95     if (der1->len != der2->len)
    96 	return (der1->len < der2->len) ? -1 : 1;
    98     for (j = 0; j < der1->len; j++) {
    99 	if (der1->data[j] == der2->data[j])
   100 	    continue;
   101 	return (der1->data[j] < der2->data[j]) ? -1 : 1;
   102     }
   103     return 0;
   104 }
   106 /*
   107  * NSS_CMSAlgArray_GetIndexByAlgID - find a specific algorithm in an array of 
   108  * algorithms.
   109  *
   110  * algorithmArray - array of algorithm IDs
   111  * algid - algorithmid of algorithm to pick
   112  *
   113  * Returns:
   114  *  An integer containing the index of the algorithm in the array or -1 if 
   115  *  algorithm was not found.
   116  */
   117 int
   118 NSS_CMSAlgArray_GetIndexByAlgID(SECAlgorithmID **algorithmArray, SECAlgorithmID *algid)
   119 {
   120     int i;
   122     if (algorithmArray == NULL || algorithmArray[0] == NULL)
   123 	return -1;
   125     for (i = 0; algorithmArray[i] != NULL; i++) {
   126 	if (SECOID_CompareAlgorithmID(algorithmArray[i], algid) == SECEqual)
   127 	    break;	/* bingo */
   128     }
   130     if (algorithmArray[i] == NULL)
   131 	return -1;	/* not found */
   133     return i;
   134 }
   136 /*
   137  * NSS_CMSAlgArray_GetIndexByAlgTag - find a specific algorithm in an array of 
   138  * algorithms.
   139  *
   140  * algorithmArray - array of algorithm IDs
   141  * algtag - algorithm tag of algorithm to pick
   142  *
   143  * Returns:
   144  *  An integer containing the index of the algorithm in the array or -1 if 
   145  *  algorithm was not found.
   146  */
   147 int
   148 NSS_CMSAlgArray_GetIndexByAlgTag(SECAlgorithmID **algorithmArray, 
   149                                  SECOidTag algtag)
   150 {
   151     SECOidData *algid;
   152     int i = -1;
   154     if (algorithmArray == NULL || algorithmArray[0] == NULL)
   155 	return i;
   157 #ifdef ORDER_N_SQUARED
   158     for (i = 0; algorithmArray[i] != NULL; i++) {
   159 	algid = SECOID_FindOID(&(algorithmArray[i]->algorithm));
   160 	if (algid->offset == algtag)
   161 	    break;	/* bingo */
   162     }
   163 #else
   164     algid = SECOID_FindOIDByTag(algtag);
   165     if (!algid) 
   166     	return i;
   167     for (i = 0; algorithmArray[i] != NULL; i++) {
   168 	if (SECITEM_ItemsAreEqual(&algorithmArray[i]->algorithm, &algid->oid))
   169 	    break;	/* bingo */
   170     }
   171 #endif
   173     if (algorithmArray[i] == NULL)
   174 	return -1;	/* not found */
   176     return i;
   177 }
   179 /*
   180  * Map a sign algorithm to a digest algorithm.
   181  * This is used to handle incorrectly formatted packages sent to us
   182  * from Windows 2003.
   183  */
   184 SECOidTag
   185 NSS_CMSUtil_MapSignAlgs(SECOidTag signAlg)
   186 {
   187     switch (signAlg) {
   188     case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
   189 	return SEC_OID_MD2;
   190 	break;
   191     case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
   192 	return SEC_OID_MD5;
   193 	break;
   194     case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
   195     case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
   196     case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
   197 	return SEC_OID_SHA1;
   198 	break;
   199     case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
   200     case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
   201 	return SEC_OID_SHA256;
   202 	break;
   203     case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
   204     case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
   205 	return SEC_OID_SHA384;
   206 	break;
   207     case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
   208     case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
   209 	return SEC_OID_SHA512;
   210 	break;
   211     default:
   212 	break;
   213     }
   214     /* not one of the algtags incorrectly sent to us*/
   215     return signAlg;
   216 }
   218 const SECHashObject *
   219 NSS_CMSUtil_GetHashObjByAlgID(SECAlgorithmID *algid)
   220 {
   221     SECOidTag oidTag = SECOID_FindOIDTag(&(algid->algorithm));
   222     const SECHashObject *digobj = HASH_GetHashObjectByOidTag(oidTag);
   224     return digobj;
   225 }
   227 const SEC_ASN1Template *
   228 NSS_CMSUtil_GetTemplateByTypeTag(SECOidTag type)
   229 {
   230     const SEC_ASN1Template *template;
   231     extern const SEC_ASN1Template NSSCMSSignedDataTemplate[];
   232     extern const SEC_ASN1Template NSSCMSEnvelopedDataTemplate[];
   233     extern const SEC_ASN1Template NSSCMSEncryptedDataTemplate[];
   234     extern const SEC_ASN1Template NSSCMSDigestedDataTemplate[];
   236     switch (type) {
   237     case SEC_OID_PKCS7_SIGNED_DATA:
   238 	template = NSSCMSSignedDataTemplate;
   239 	break;
   240     case SEC_OID_PKCS7_ENVELOPED_DATA:
   241 	template = NSSCMSEnvelopedDataTemplate;
   242 	break;
   243     case SEC_OID_PKCS7_ENCRYPTED_DATA:
   244 	template = NSSCMSEncryptedDataTemplate;
   245 	break;
   246     case SEC_OID_PKCS7_DIGESTED_DATA:
   247 	template = NSSCMSDigestedDataTemplate;
   248 	break;
   249     default:
   250 	template = NSS_CMSType_GetTemplate(type);
   251 	break;
   252     }
   253     return template;
   254 }
   256 size_t
   257 NSS_CMSUtil_GetSizeByTypeTag(SECOidTag type)
   258 {
   259     size_t size;
   261     switch (type) {
   262     case SEC_OID_PKCS7_SIGNED_DATA:
   263 	size = sizeof(NSSCMSSignedData);
   264 	break;
   265     case SEC_OID_PKCS7_ENVELOPED_DATA:
   266 	size = sizeof(NSSCMSEnvelopedData);
   267 	break;
   268     case SEC_OID_PKCS7_ENCRYPTED_DATA:
   269 	size = sizeof(NSSCMSEncryptedData);
   270 	break;
   271     case SEC_OID_PKCS7_DIGESTED_DATA:
   272 	size = sizeof(NSSCMSDigestedData);
   273 	break;
   274     default:
   275 	size = NSS_CMSType_GetContentSize(type);
   276 	break;
   277     }
   278     return size;
   279 }
   281 NSSCMSContentInfo *
   282 NSS_CMSContent_GetContentInfo(void *msg, SECOidTag type)
   283 {
   284     NSSCMSContent c;
   285     NSSCMSContentInfo *cinfo = NULL;
   287     if (!msg)
   288 	return cinfo;
   289     c.pointer = msg;
   290     switch (type) {
   291     case SEC_OID_PKCS7_SIGNED_DATA:
   292 	cinfo = &(c.signedData->contentInfo);
   293 	break;
   294     case SEC_OID_PKCS7_ENVELOPED_DATA:
   295 	cinfo = &(c.envelopedData->contentInfo);
   296 	break;
   297     case SEC_OID_PKCS7_ENCRYPTED_DATA:
   298 	cinfo = &(c.encryptedData->contentInfo);
   299 	break;
   300     case SEC_OID_PKCS7_DIGESTED_DATA:
   301 	cinfo = &(c.digestedData->contentInfo);
   302 	break;
   303     default:
   304 	cinfo = NULL;
   305 	if (NSS_CMSType_IsWrapper(type)) {
   306 	    cinfo = &(c.genericData->contentInfo);
   307 	}
   308     }
   309     return cinfo;
   310 }
   312 const char *
   313 NSS_CMSUtil_VerificationStatusToString(NSSCMSVerificationStatus vs)
   314 {
   315     switch (vs) {
   316     case NSSCMSVS_Unverified:			return "Unverified";
   317     case NSSCMSVS_GoodSignature:		return "GoodSignature";
   318     case NSSCMSVS_BadSignature:			return "BadSignature";
   319     case NSSCMSVS_DigestMismatch:		return "DigestMismatch";
   320     case NSSCMSVS_SigningCertNotFound:		return "SigningCertNotFound";
   321     case NSSCMSVS_SigningCertNotTrusted:	return "SigningCertNotTrusted";
   322     case NSSCMSVS_SignatureAlgorithmUnknown:	return "SignatureAlgorithmUnknown";
   323     case NSSCMSVS_SignatureAlgorithmUnsupported: return "SignatureAlgorithmUnsupported";
   324     case NSSCMSVS_MalformedSignature:		return "MalformedSignature";
   325     case NSSCMSVS_ProcessingError:		return "ProcessingError";
   326     default:					return "Unknown";
   327     }
   328 }
   330 SECStatus
   331 NSS_CMSDEREncode(NSSCMSMessage *cmsg, SECItem *input, SECItem *derOut, 
   332                  PLArenaPool *arena)
   333 {
   334     NSSCMSEncoderContext *ecx;
   335     SECStatus rv = SECSuccess;
   336     if (!cmsg || !derOut || !arena) {
   337 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   338 	return SECFailure;
   339     }
   340     ecx = NSS_CMSEncoder_Start(cmsg, 0, 0, derOut, arena, 0, 0, 0, 0, 0, 0);
   341     if (!ecx) {
   342 	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   343 	return SECFailure;
   344     }
   345     if (input) {
   346 	rv = NSS_CMSEncoder_Update(ecx, (const char*)input->data, input->len);
   347 	if (rv) {
   348 	    PORT_SetError(SEC_ERROR_BAD_DATA);
   349 	}
   350     }
   351     rv |= NSS_CMSEncoder_Finish(ecx);
   352     if (rv) {
   353 	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   354     }
   355     return rv;
   356 }

mercurial