security/nss/lib/crmf/crmfdec.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 /* -*- Mode: C; tab-width: 8 -*-*/
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "crmf.h"
     8 #include "crmfi.h"
     9 #include "secitem.h"
    11 static CRMFPOPChoice
    12 crmf_get_popchoice_from_der(SECItem *derPOP)
    13 {
    14     CRMFPOPChoice retChoice;
    16     switch (derPOP->data[0] & 0x0f) {
    17     case 0:
    18         retChoice = crmfRAVerified;
    19 	break;
    20     case 1:
    21         retChoice = crmfSignature;
    22 	break;
    23     case 2:
    24         retChoice = crmfKeyEncipherment;
    25 	break;
    26     case 3:
    27         retChoice = crmfKeyAgreement;
    28 	break;
    29     default:
    30         retChoice = crmfNoPOPChoice;
    31 	break;
    32     }
    33     return retChoice;
    34 }
    36 static SECStatus
    37 crmf_decode_process_raverified(CRMFCertReqMsg *inCertReqMsg)
    38 {   
    39     CRMFProofOfPossession *pop;
    40     /* Just set up the structure so that the message structure
    41      * looks like one that was created using the API
    42      */
    43     pop = inCertReqMsg->pop;
    44     pop->popChoice.raVerified.data = NULL;
    45     pop->popChoice.raVerified.len  = 0;
    46     return SECSuccess;
    47 }
    49 static SECStatus
    50 crmf_decode_process_signature(CRMFCertReqMsg *inCertReqMsg)
    51 {
    52     PORT_Assert(inCertReqMsg->poolp);
    53     if (!inCertReqMsg->poolp) {
    54     	PORT_SetError(SEC_ERROR_INVALID_ARGS);
    55 	return SECFailure;
    56     }
    57     return SEC_ASN1Decode(inCertReqMsg->poolp,
    58 			  &inCertReqMsg->pop->popChoice.signature,
    59 			  CRMFPOPOSigningKeyTemplate, 
    60 			  (const char*)inCertReqMsg->derPOP.data,
    61 			  inCertReqMsg->derPOP.len);
    62 }
    64 static CRMFPOPOPrivKeyChoice
    65 crmf_get_messagechoice_from_der(SECItem *derPOP)
    66 {
    67     CRMFPOPOPrivKeyChoice retChoice;
    69     switch (derPOP->data[2] & 0x0f) {
    70     case 0:
    71         retChoice = crmfThisMessage;
    72 	break;
    73     case 1:
    74         retChoice = crmfSubsequentMessage;
    75 	break;
    76     case 2:
    77         retChoice = crmfDHMAC;
    78 	break;
    79     default:
    80         retChoice = crmfNoMessage;
    81     }
    82     return retChoice;
    83 }
    85 static SECStatus
    86 crmf_decode_process_popoprivkey(CRMFCertReqMsg *inCertReqMsg)
    87 {
    88     /* We've got a union, so a pointer to one POPOPrivKey
    89      * struct is the same as having a pointer to the other 
    90      * one.
    91      */
    92     CRMFPOPOPrivKey *popoPrivKey = 
    93                     &inCertReqMsg->pop->popChoice.keyEncipherment;
    94     SECItem         *derPOP, privKeyDer;
    95     SECStatus        rv;
    97     derPOP = &inCertReqMsg->derPOP;
    98     popoPrivKey->messageChoice = crmf_get_messagechoice_from_der(derPOP);
    99     if (popoPrivKey->messageChoice == crmfNoMessage) {
   100         return SECFailure;
   101     }
   102     /* If we ever encounter BER encodings of this, we'll get in trouble*/
   103     switch (popoPrivKey->messageChoice) {
   104     case crmfThisMessage:
   105     case crmfDHMAC:
   106         privKeyDer.type = derPOP->type;
   107         privKeyDer.data = &derPOP->data[5];
   108 	privKeyDer.len  = derPOP->len - 5;
   109 	break;
   110     case crmfSubsequentMessage:
   111         privKeyDer.type = derPOP->type;
   112         privKeyDer.data = &derPOP->data[4];
   113 	privKeyDer.len  = derPOP->len - 4;
   114 	break;
   115     default:
   116         return SECFailure;
   117     }
   119     rv = SECITEM_CopyItem(inCertReqMsg->poolp, 
   120 			  &popoPrivKey->message.subsequentMessage,
   121 			  &privKeyDer);
   123     if (rv != SECSuccess) {
   124         return rv;
   125     }
   127     if (popoPrivKey->messageChoice == crmfThisMessage ||
   128 	popoPrivKey->messageChoice == crmfDHMAC) {
   130         popoPrivKey->message.thisMessage.len = 
   131 	    CRMF_BYTES_TO_BITS(privKeyDer.len) - (int)derPOP->data[4];
   133     }
   134     return SECSuccess;    
   135 }
   137 static SECStatus
   138 crmf_decode_process_keyagreement(CRMFCertReqMsg *inCertReqMsg)
   139 {
   140     return crmf_decode_process_popoprivkey(inCertReqMsg);
   141 }
   143 static SECStatus
   144 crmf_decode_process_keyencipherment(CRMFCertReqMsg *inCertReqMsg)
   145 {
   146     SECStatus rv;
   148     rv = crmf_decode_process_popoprivkey(inCertReqMsg);
   149     if (rv != SECSuccess) {
   150         return rv;
   151     }
   152     if (inCertReqMsg->pop->popChoice.keyEncipherment.messageChoice == 
   153 	crmfDHMAC) {
   154         /* Key Encipherment can not use the dhMAC option for
   155 	 * POPOPrivKey. 
   156 	 */
   157         return SECFailure;
   158     }
   159     return SECSuccess;
   160 }
   162 static SECStatus
   163 crmf_decode_process_pop(CRMFCertReqMsg *inCertReqMsg)
   164 {
   165      SECItem               *derPOP;
   166      PLArenaPool           *poolp;
   167      CRMFProofOfPossession *pop;
   168      void                  *mark;
   169      SECStatus              rv;
   171      derPOP = &inCertReqMsg->derPOP;
   172      poolp  = inCertReqMsg->poolp;
   173      if (derPOP->data == NULL) {
   174          /* There is no Proof of Possession field in this message. */
   175          return SECSuccess;
   176      }
   177      mark = PORT_ArenaMark(poolp);
   178      pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
   179      if (pop == NULL) {
   180          goto loser;
   181      }
   182      pop->popUsed = crmf_get_popchoice_from_der(derPOP);
   183      if (pop->popUsed == crmfNoPOPChoice) {
   184          /* A bad encoding of CRMF.  Not a valid tag was given to the
   185 	  * Proof Of Possession field.
   186 	  */
   187          goto loser;
   188      }
   189      inCertReqMsg->pop = pop;
   190      switch (pop->popUsed) {
   191      case crmfRAVerified:
   192          rv = crmf_decode_process_raverified(inCertReqMsg);
   193 	 break;
   194      case crmfSignature:
   195          rv = crmf_decode_process_signature(inCertReqMsg);
   196 	 break;
   197      case crmfKeyEncipherment:
   198          rv = crmf_decode_process_keyencipherment(inCertReqMsg);
   199 	 break;
   200      case crmfKeyAgreement:
   201          rv = crmf_decode_process_keyagreement(inCertReqMsg);
   202 	 break;
   203      default:
   204          rv = SECFailure;
   205      }
   206      if (rv != SECSuccess) {
   207          goto loser;
   208      }
   209      PORT_ArenaUnmark(poolp, mark);
   210      return SECSuccess;
   212  loser:
   213      PORT_ArenaRelease(poolp, mark);
   214      inCertReqMsg->pop = NULL;
   215      return SECFailure;
   217 }
   219 static SECStatus
   220 crmf_decode_process_single_control(PLArenaPool *poolp,
   221 				   CRMFControl *inControl)
   222 {
   223     const SEC_ASN1Template *asn1Template = NULL;
   225     inControl->tag = SECOID_FindOIDTag(&inControl->derTag);
   226     asn1Template = crmf_get_pkiarchiveoptions_subtemplate(inControl);
   228     PORT_Assert (asn1Template != NULL);
   229     PORT_Assert (poolp != NULL);
   230     if (!asn1Template || !poolp) {
   231     	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   232 	return SECFailure;
   233     }
   234     /* We've got a union, so passing a pointer to one element of the
   235      * union is the same as passing a pointer to any of the other
   236      * members of the union.
   237      */
   238     return SEC_ASN1Decode(poolp, &inControl->value.archiveOptions, 
   239 			  asn1Template, (const char*)inControl->derValue.data,
   240 			  inControl->derValue.len);
   241 }
   243 static SECStatus 
   244 crmf_decode_process_controls(CRMFCertReqMsg *inCertReqMsg)
   245 {
   246     int           i, numControls;
   247     SECStatus     rv;
   248     PLArenaPool  *poolp;
   249     CRMFControl **controls;
   251     numControls = CRMF_CertRequestGetNumControls(inCertReqMsg->certReq);
   252     controls = inCertReqMsg->certReq->controls;
   253     poolp    = inCertReqMsg->poolp;
   254     for (i=0; i < numControls; i++) {
   255         rv = crmf_decode_process_single_control(poolp, controls[i]);
   256 	if (rv != SECSuccess) {
   257 	    return SECFailure;
   258 	}
   259     }
   260     return SECSuccess;
   261 }
   263 static SECStatus
   264 crmf_decode_process_single_reqmsg(CRMFCertReqMsg *inCertReqMsg)
   265 {
   266     SECStatus rv;
   268     rv = crmf_decode_process_pop(inCertReqMsg);
   269     if (rv != SECSuccess) {
   270         goto loser;
   271     }
   273     rv = crmf_decode_process_controls(inCertReqMsg);
   274     if (rv != SECSuccess) {
   275         goto loser;
   276     }
   277     inCertReqMsg->certReq->certTemplate.numExtensions = 
   278         CRMF_CertRequestGetNumberOfExtensions(inCertReqMsg->certReq);
   279     inCertReqMsg->isDecoded = PR_TRUE;
   280     rv = SECSuccess;
   281  loser:
   282     return rv;
   283 }
   285 CRMFCertReqMsg*
   286 CRMF_CreateCertReqMsgFromDER (const char * buf, long len)
   287 {
   288     PLArenaPool    *poolp;
   289     CRMFCertReqMsg *certReqMsg;
   290     SECStatus       rv;
   292     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
   293     if (poolp == NULL) {
   294         goto loser;
   295     }
   296     certReqMsg = PORT_ArenaZNew (poolp, CRMFCertReqMsg);
   297     if (certReqMsg == NULL) {
   298         goto loser;
   299     }
   300     certReqMsg->poolp = poolp;
   301     rv = SEC_ASN1Decode(poolp, certReqMsg, CRMFCertReqMsgTemplate, buf, len);
   302     if (rv != SECSuccess) {
   303         goto loser;
   304     }
   306     rv = crmf_decode_process_single_reqmsg(certReqMsg);
   307     if (rv != SECSuccess) {
   308         goto loser;
   309     }
   311     return certReqMsg;
   312  loser:
   313     if (poolp != NULL) {
   314         PORT_FreeArena(poolp, PR_FALSE);
   315     }
   316     return NULL;
   317 }
   319 CRMFCertReqMessages*
   320 CRMF_CreateCertReqMessagesFromDER(const char *buf, long len)
   321 {
   322     long                 arenaSize;
   323     int                  i;
   324     SECStatus            rv;
   325     PLArenaPool         *poolp;
   326     CRMFCertReqMessages *certReqMsgs;
   328     PORT_Assert (buf != NULL);
   329     /* Wanna make sure the arena is big enough to store all of the requests
   330      * coming in.  We'll guestimate according to the length of the buffer.
   331      */
   332     arenaSize = len + len/2;
   333     poolp = PORT_NewArena(arenaSize);
   334     if (poolp == NULL) {
   335         return NULL;
   336     }
   337     certReqMsgs = PORT_ArenaZNew(poolp, CRMFCertReqMessages);
   338     if (certReqMsgs == NULL) {
   339         goto loser;
   340     }
   341     certReqMsgs->poolp = poolp;
   342     rv = SEC_ASN1Decode(poolp, certReqMsgs, CRMFCertReqMessagesTemplate,
   343 			buf, len);
   344     if (rv != SECSuccess) {
   345         goto loser;
   346     }
   347     for (i=0; certReqMsgs->messages[i] != NULL; i++) {
   348         /* The sub-routines expect the individual messages to have 
   349 	 * an arena.  We'll give them one temporarily.
   350 	 */
   351         certReqMsgs->messages[i]->poolp = poolp;
   352         rv = crmf_decode_process_single_reqmsg(certReqMsgs->messages[i]);
   353 	if (rv != SECSuccess) {
   354 	    goto loser;
   355 	}
   356         certReqMsgs->messages[i]->poolp = NULL;
   357     }
   358     return certReqMsgs;
   360  loser:
   361     PORT_FreeArena(poolp, PR_FALSE);
   362     return NULL;
   363 }

mercurial