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.

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

mercurial