security/manager/ssl/src/nsNSSASN1Object.cpp

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     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/. */
     4 #include "nsNSSASN1Object.h"
     5 #include "nsIComponentManager.h"
     6 #include "secasn1.h"
     7 #include "nsReadableUtils.h"
     8 #include "nsIMutableArray.h"
     9 #include "nsArrayUtils.h"
    10 #include "nsXPCOMCID.h"
    12 NS_IMPL_ISUPPORTS(nsNSSASN1Sequence, nsIASN1Sequence, nsIASN1Object)
    13 NS_IMPL_ISUPPORTS(nsNSSASN1PrintableItem, nsIASN1PrintableItem, nsIASN1Object)
    15 // This function is used to interpret an integer that
    16 // was encoded in a DER buffer. This function is used
    17 // when converting a DER buffer into a nsIASN1Object 
    18 // structure.  This interprets the buffer in data
    19 // as defined by the DER (Distinguised Encoding Rules) of
    20 // ASN1.
    21 static int
    22 getInteger256(unsigned char *data, unsigned int nb)
    23 {
    24     int val;
    26     switch (nb) {
    27       case 1:
    28         val = data[0];
    29         break;
    30       case 2:
    31         val = (data[0] << 8) | data[1];
    32         break;
    33       case 3:
    34         val = (data[0] << 16) | (data[1] << 8) | data[2];
    35         break;
    36       case 4:
    37         val = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
    38         break;
    39       default:
    40         return -1;
    41     }
    43     return val;
    44 }
    46 // This function is used to retrieve the lenght of a DER encoded
    47 // item.  It looks to see if this a multibyte length and then
    48 // interprets the buffer accordingly to get the actual length value.
    49 // This funciton is used mostly while parsing the DER headers.
    50 // 
    51 // A DER encoded item has the following structure:
    52 //
    53 //  <tag><length<data consisting of lenght bytes>
    54 static int32_t
    55 getDERItemLength(unsigned char *data, unsigned char *end,
    56                  unsigned long *bytesUsed, bool *indefinite)
    57 {
    58   unsigned char lbyte = *data++;
    59   int32_t length = -1;
    61   *indefinite = false;
    62   if (lbyte >= 0x80) {
    63     // Multibyte length
    64     unsigned nb = (unsigned) (lbyte & 0x7f);
    65     if (nb > 4) {
    66       return -1;
    67     }
    68     if (nb > 0) {
    70       if ((data+nb) > end) {
    71         return -1;
    72       }
    73       length = getInteger256(data, nb);
    74       if (length < 0)
    75         return -1;
    76     } else {
    77       *indefinite = true;
    78       length = 0;
    79     }
    80     *bytesUsed = nb+1;
    81   } else {
    82     length = lbyte;
    83     *bytesUsed = 1; 
    84   }
    85   return length;
    86 }
    88 static nsresult
    89 buildASN1ObjectFromDER(unsigned char *data,
    90                        unsigned char *end,
    91                        nsIASN1Sequence *parent)
    92 {
    93   nsresult rv;
    94   nsCOMPtr<nsIASN1Sequence> sequence;
    95   nsCOMPtr<nsIASN1PrintableItem> printableItem;
    96   nsCOMPtr<nsIASN1Object> asn1Obj;
    97   nsCOMPtr<nsIMutableArray> parentObjects;
    99   NS_ENSURE_ARG_POINTER(parent);
   100   if (data >= end)
   101     return NS_OK;
   103   unsigned char code, tagnum;
   105   // A DER item has the form of |tag|len|data
   106   // tag is one byte and describes the type of element
   107   //     we are dealing with.
   108   // len is a DER encoded int telling us how long the data is
   109   // data is a buffer that is len bytes long and has to be
   110   //      interpreted according to its type.
   111   unsigned long bytesUsed;
   112   bool indefinite;
   113   int32_t len;
   114   uint32_t type;
   116   rv = parent->GetASN1Objects(getter_AddRefs(parentObjects));
   117   if (NS_FAILED(rv) || !parentObjects)
   118     return NS_ERROR_FAILURE;
   119   while (data < end) {
   120     code = *data;
   121     tagnum = code & SEC_ASN1_TAGNUM_MASK;
   123     /*
   124      * NOTE: This code does not (yet) handle the high-tag-number form!
   125      */
   126     if (tagnum == SEC_ASN1_HIGH_TAG_NUMBER) {
   127       return NS_ERROR_FAILURE;
   128     }
   129     data++;
   130     len = getDERItemLength(data, end, &bytesUsed, &indefinite);
   131     data += bytesUsed;
   132     if ((len < 0) || ((data+len) > end))
   133       return NS_ERROR_FAILURE;
   135     if (code & SEC_ASN1_CONSTRUCTED) {
   136       if (len > 0 || indefinite) {
   137         sequence = new nsNSSASN1Sequence();
   138         switch (code & SEC_ASN1_CLASS_MASK) {
   139         case SEC_ASN1_UNIVERSAL:
   140           type = tagnum;
   141           break;
   142         case SEC_ASN1_APPLICATION:
   143           type = nsIASN1Object::ASN1_APPLICATION;
   144           break;
   145         case SEC_ASN1_CONTEXT_SPECIFIC:
   146           type = nsIASN1Object::ASN1_CONTEXT_SPECIFIC;
   147           break;
   148         case SEC_ASN1_PRIVATE:
   149           type = nsIASN1Object::ASN1_PRIVATE;
   150           break;
   151         default:
   152           NS_ERROR("Bad DER");
   153           return NS_ERROR_FAILURE;
   154         }
   155         sequence->SetTag(tagnum);
   156         sequence->SetType(type);
   157         rv = buildASN1ObjectFromDER(data, (len == 0) ? end : data + len, 
   158                                     sequence);
   159         asn1Obj = sequence;
   160       }
   161     } else {
   162       printableItem = new nsNSSASN1PrintableItem();
   164       asn1Obj = printableItem;
   165       asn1Obj->SetType(tagnum);
   166       asn1Obj->SetTag(tagnum); 
   167       printableItem->SetData((char*)data, len);
   168     }
   169     data += len;
   170     parentObjects->AppendElement(asn1Obj, false);
   171   }
   173   return NS_OK;
   174 }
   176 nsresult
   177 CreateFromDER(unsigned char *data,
   178               unsigned int   len,
   179               nsIASN1Object **retval)
   180 {
   181   nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence;
   182   *retval = nullptr;
   184   nsresult rv =  buildASN1ObjectFromDER(data, data+len, sequence);
   186   if (NS_SUCCEEDED(rv)) {
   187     // The actual object will be the first element inserted
   188     // into the sequence of the sequence variable we created.
   189     nsCOMPtr<nsIMutableArray> elements;
   191     sequence->GetASN1Objects(getter_AddRefs(elements));
   192     nsCOMPtr<nsIASN1Object> asn1Obj = do_QueryElementAt(elements, 0);
   193     *retval = asn1Obj;
   194     if (!*retval)
   195       return NS_ERROR_FAILURE;
   197     NS_ADDREF(*retval);
   199   }
   200   return rv; 
   201 }
   203 nsNSSASN1Sequence::nsNSSASN1Sequence() : mType(0),
   204                                          mTag(0),
   205                                          mIsValidContainer(true),
   206                                          mIsExpanded(true)
   207 {
   208   /* member initializers and constructor code */
   209 }
   211 nsNSSASN1Sequence::~nsNSSASN1Sequence()
   212 {
   213   /* destructor code */
   214 }
   216 NS_IMETHODIMP 
   217 nsNSSASN1Sequence::GetASN1Objects(nsIMutableArray * *aASN1Objects)
   218 {
   219   if (!mASN1Objects) {
   220     mASN1Objects = do_CreateInstance(NS_ARRAY_CONTRACTID);
   221   }
   222   *aASN1Objects = mASN1Objects;
   223   NS_IF_ADDREF(*aASN1Objects);
   224   return NS_OK;
   225 }
   227 NS_IMETHODIMP 
   228 nsNSSASN1Sequence::SetASN1Objects(nsIMutableArray * aASN1Objects)
   229 {
   230   mASN1Objects = aASN1Objects;
   231   return NS_OK;
   232 }
   234 NS_IMETHODIMP 
   235 nsNSSASN1Sequence::GetTag(uint32_t *aTag)
   236 {
   237   *aTag = mTag;
   238   return NS_OK;
   239 }
   241 NS_IMETHODIMP 
   242 nsNSSASN1Sequence::SetTag(uint32_t aTag)
   243 {
   244   mTag = aTag;
   245   return NS_OK;
   246 }
   248 NS_IMETHODIMP 
   249 nsNSSASN1Sequence::GetType(uint32_t *aType)
   250 {
   251   *aType = mType;
   252   return NS_OK;
   253 }
   255 NS_IMETHODIMP 
   256 nsNSSASN1Sequence::SetType(uint32_t aType)
   257 {
   258   mType = aType;
   259   return NS_OK;
   260 }
   262 NS_IMETHODIMP 
   263 nsNSSASN1Sequence::GetDisplayName(nsAString &aDisplayName)
   264 {
   265   aDisplayName = mDisplayName;
   266   return NS_OK;
   267 }
   269 NS_IMETHODIMP 
   270 nsNSSASN1Sequence::SetDisplayName(const nsAString &aDisplayName)
   271 {
   272   mDisplayName = aDisplayName;
   273   return NS_OK;
   274 }
   276 NS_IMETHODIMP 
   277 nsNSSASN1Sequence::GetDisplayValue(nsAString &aDisplayValue)
   278 {
   279   aDisplayValue = mDisplayValue;
   280   return NS_OK;
   281 }
   283 NS_IMETHODIMP 
   284 nsNSSASN1Sequence::SetDisplayValue(const nsAString &aDisplayValue)
   285 {
   286   mDisplayValue = aDisplayValue;
   287   return NS_OK;
   288 }
   290 NS_IMETHODIMP 
   291 nsNSSASN1Sequence::GetIsValidContainer(bool *aIsValidContainer)
   292 {
   293   NS_ENSURE_ARG_POINTER(aIsValidContainer);
   294   *aIsValidContainer = mIsValidContainer;
   295   return NS_OK;
   296 }
   298 NS_IMETHODIMP
   299 nsNSSASN1Sequence::SetIsValidContainer(bool aIsValidContainer)
   300 {
   301   mIsValidContainer = aIsValidContainer;
   302   SetIsExpanded(mIsValidContainer);
   303   return NS_OK;
   304 }
   306 NS_IMETHODIMP 
   307 nsNSSASN1Sequence::GetIsExpanded(bool *aIsExpanded)
   308 {
   309   NS_ENSURE_ARG_POINTER(aIsExpanded);
   310   *aIsExpanded = mIsExpanded;
   311   return NS_OK;
   312 }
   314 NS_IMETHODIMP 
   315 nsNSSASN1Sequence::SetIsExpanded(bool aIsExpanded)
   316 {
   317   mIsExpanded = aIsExpanded;
   318   return NS_OK;
   319 }
   322 nsNSSASN1PrintableItem::nsNSSASN1PrintableItem() : mType(0),
   323                                                    mTag(0),
   324                                                    mData(nullptr),
   325                                                    mLen(0)
   326 {
   327   /* member initializers and constructor code */
   328 }
   330 nsNSSASN1PrintableItem::~nsNSSASN1PrintableItem()
   331 {
   332   /* destructor code */
   333   if (mData)
   334     nsMemory::Free(mData);
   335 }
   337 /* readonly attribute wstring value; */
   338 NS_IMETHODIMP 
   339 nsNSSASN1PrintableItem::GetDisplayValue(nsAString &aValue)
   340 {
   341   aValue = mValue;
   342   return NS_OK;
   343 }
   345 NS_IMETHODIMP 
   346 nsNSSASN1PrintableItem::SetDisplayValue(const nsAString &aValue)
   347 {
   348   mValue = aValue;
   349   return NS_OK;
   350 }
   352 NS_IMETHODIMP 
   353 nsNSSASN1PrintableItem::GetTag(uint32_t *aTag)
   354 {
   355   *aTag = mTag;
   356   return NS_OK;
   357 }
   359 NS_IMETHODIMP 
   360 nsNSSASN1PrintableItem::SetTag(uint32_t aTag)
   361 {
   362   mTag = aTag;
   363   return NS_OK;
   364 }
   366 NS_IMETHODIMP 
   367 nsNSSASN1PrintableItem::GetType(uint32_t *aType)
   368 {
   369   *aType = mType;
   370   return NS_OK;
   371 }
   373 NS_IMETHODIMP 
   374 nsNSSASN1PrintableItem::SetType(uint32_t aType)
   375 {
   376   mType = aType;
   377   return NS_OK;
   378 }
   380 NS_IMETHODIMP 
   381 nsNSSASN1PrintableItem::SetData(char *data, uint32_t len)
   382 {
   383   if (len > 0) {
   384     if (mLen < len) {
   385       unsigned char* newData = (unsigned char*)nsMemory::Realloc(mData, len);
   386       if (!newData)
   387         return NS_ERROR_OUT_OF_MEMORY;
   389       mData = newData;
   390     }
   392     memcpy(mData, data, len);
   393   } else if (len == 0) {
   394     if (mData) {
   395       nsMemory::Free(mData);
   396       mData = nullptr;
   397     }
   398   }
   399   mLen = len;
   400   return NS_OK;  
   401 }
   403 NS_IMETHODIMP
   404 nsNSSASN1PrintableItem::GetData(char **outData, uint32_t *outLen)
   405 {
   406   NS_ENSURE_ARG_POINTER(outData);
   407   NS_ENSURE_ARG_POINTER(outLen);
   409   *outData = (char*)mData;
   410   *outLen  = mLen;
   411   return NS_OK;
   412 }
   414 /* attribute wstring displayName; */
   415 NS_IMETHODIMP 
   416 nsNSSASN1PrintableItem::GetDisplayName(nsAString &aDisplayName)
   417 {
   418   aDisplayName = mDisplayName;
   419   return NS_OK;
   420 }
   422 NS_IMETHODIMP 
   423 nsNSSASN1PrintableItem::SetDisplayName(const nsAString &aDisplayName)
   424 {
   425   mDisplayName = aDisplayName;
   426   return NS_OK;
   427 }

mercurial