tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

der_quickder_unittest.cc (3895B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <stdint.h>
      8 
      9 #include "gtest/gtest.h"
     10 #include "scoped_ptrs_util.h"
     11 
     12 #include "nss.h"
     13 #include "prerror.h"
     14 #include "secasn1.h"
     15 #include "secder.h"
     16 #include "secerr.h"
     17 #include "secitem.h"
     18 
     19 namespace nss_test {
     20 
     21 struct TemplateAndInput {
     22  const SEC_ASN1Template* t;
     23  SECItem input;
     24 };
     25 
     26 class QuickDERTest : public ::testing::Test,
     27                     public ::testing::WithParamInterface<TemplateAndInput> {};
     28 
     29 static const uint8_t kBitstringTag = 0x03;
     30 static const uint8_t kNullTag = 0x05;
     31 static const uint8_t kLongLength = 0x80;
     32 
     33 const SEC_ASN1Template kBitstringTemplate[] = {
     34    {SEC_ASN1_BIT_STRING, 0, NULL, sizeof(SECItem)}, {0}};
     35 
     36 // Empty bitstring with unused bits.
     37 static uint8_t kEmptyBitstringUnused[] = {kBitstringTag, 1, 1};
     38 
     39 // Bitstring with 8 unused bits.
     40 static uint8_t kBitstring8Unused[] = {kBitstringTag, 3, 8, 0xff, 0x00};
     41 
     42 // Bitstring with >8 unused bits.
     43 static uint8_t kBitstring9Unused[] = {kBitstringTag, 3, 9, 0xff, 0x80};
     44 
     45 const SEC_ASN1Template kNullTemplate[] = {
     46    {SEC_ASN1_NULL, 0, NULL, sizeof(SECItem)}, {0}};
     47 
     48 // Length of zero wrongly encoded as 0x80 instead of 0x00.
     49 static uint8_t kOverlongLength_0_0[] = {kNullTag, kLongLength | 0};
     50 
     51 // Length of zero wrongly encoded as { 0x81, 0x00 } instead of 0x00.
     52 static uint8_t kOverlongLength_1_0[] = {kNullTag, kLongLength | 1, 0x00};
     53 
     54 // Length of zero wrongly encoded as:
     55 //
     56 //     { 0x90, <arbitrary junk of 12 bytes>,
     57 //       0x00, 0x00, 0x00, 0x00 }
     58 //
     59 // instead of 0x00. Note in particular that if there is an integer overflow
     60 // then the arbitrary junk is likely get left-shifted away, as long as there
     61 // are at least sizeof(length) bytes following it. This would be a good way to
     62 // smuggle arbitrary input into DER-encoded data in a way that an non-careful
     63 // parser would ignore.
     64 static uint8_t kOverlongLength_16_0[] = {kNullTag, kLongLength | 0x10,
     65                                         0x11,     0x22,
     66                                         0x33,     0x44,
     67                                         0x55,     0x66,
     68                                         0x77,     0x88,
     69                                         0x99,     0xAA,
     70                                         0xBB,     0xCC,
     71                                         0x00,     0x00,
     72                                         0x00,     0x00};
     73 
     74 #define TI(t, x)                  \
     75  {                               \
     76    t, { siBuffer, x, sizeof(x) } \
     77  }
     78 static const TemplateAndInput kInvalidDER[] = {
     79    TI(kBitstringTemplate, kEmptyBitstringUnused),
     80    TI(kBitstringTemplate, kBitstring8Unused),
     81    TI(kBitstringTemplate, kBitstring9Unused),
     82    TI(kNullTemplate, kOverlongLength_0_0),
     83    TI(kNullTemplate, kOverlongLength_1_0),
     84    TI(kNullTemplate, kOverlongLength_16_0),
     85 };
     86 #undef TI
     87 
     88 TEST_P(QuickDERTest, InvalidLengths) {
     89  const SECItem& original_input(GetParam().input);
     90 
     91  ScopedSECItem copy_of_input(SECITEM_AllocItem(nullptr, nullptr, 0U));
     92  ASSERT_TRUE(copy_of_input);
     93  ASSERT_EQ(SECSuccess,
     94            SECITEM_CopyItem(nullptr, copy_of_input.get(), &original_input));
     95 
     96  PORTCheapArenaPool pool;
     97  PORT_InitCheapArena(&pool, DER_DEFAULT_CHUNKSIZE);
     98  StackSECItem parsed_value;
     99  ASSERT_EQ(SECFailure,
    100            SEC_QuickDERDecodeItem(&pool.arena, &parsed_value, GetParam().t,
    101                                   copy_of_input.get()));
    102  ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
    103  PORT_DestroyCheapArena(&pool);
    104 }
    105 
    106 INSTANTIATE_TEST_SUITE_P(QuickderTestsInvalidLengths, QuickDERTest,
    107                         testing::ValuesIn(kInvalidDER));
    108 
    109 }  // namespace nss_test