summaryrefslogtreecommitdiff
path: root/chromium/net/cert/internal/extended_key_usage_unittest.cc
blob: a8bd055938d515a6210ce00377c087541fa5f701 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>

#include "net/cert/internal/extended_key_usage.h"
#include "net/der/input.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace net {

namespace {

// Helper method to check if an EKU is present in a std::vector of EKUs.
bool HasEKU(const std::vector<der::Input>& list, const der::Input& eku) {
  for (const auto& oid : list) {
    if (oid == eku)
      return true;
  }
  return false;
}

// Check that we can read multiple EKUs from an extension.
TEST(ExtendedKeyUsageTest, ParseEKUExtension) {
  // clang-format off
  const uint8_t raw_extension_value[] = {
      0x30, 0x14,  // SEQUENCE (20 bytes)
      0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
      0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,  // 1.3.6.1.5.5.7.3.1
      0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
      0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02  // 1.3.6.1.5.5.7.3.2
      // end of SEQUENCE
  };
  // clang-format on
  der::Input extension_value(raw_extension_value);

  std::vector<der::Input> ekus;
  EXPECT_TRUE(ParseEKUExtension(extension_value, &ekus));

  EXPECT_EQ(2u, ekus.size());
  EXPECT_TRUE(HasEKU(ekus, der::Input(kServerAuth)));
  EXPECT_TRUE(HasEKU(ekus, der::Input(kClientAuth)));
}

// Check that an extension with the same OID present multiple times doesn't
// cause an error.
TEST(ExtendedKeyUsageTest, RepeatedOid) {
  // clang-format off
  const uint8_t extension_bytes[] = {
      0x30, 0x14,  // SEQUENCE (20 bytes)
      0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
      0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,  // 1.3.6.1.5.5.7.3.1
      0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
      0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01  // 1.3.6.1.5.5.7.3.1
  };
  // clang-format on
  der::Input extension(extension_bytes);

  std::vector<der::Input> ekus;
  EXPECT_TRUE(ParseEKUExtension(extension, &ekus));
  EXPECT_EQ(2u, ekus.size());
  for (const auto& eku : ekus) {
    EXPECT_EQ(der::Input(kServerAuth), eku);
  }
}

// Check that parsing an EKU extension which contains a private OID doesn't
// cause an error.
TEST(ExtendedKeyUsageTest, ParseEKUExtensionGracefullyHandlesPrivateOids) {
  // clang-format off
  const uint8_t extension_bytes[] = {
    0x30, 0x13,  // SEQUENCE (19 bytes)
    0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
    0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,  // 1.3.6.1.5.5.7.3.1
    0x06, 0x07,  // OBJECT IDENTIFIER (7 bytes)
    0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79  // 1.3.6.1.4.1.11129
  };
  // clang-format on
  der::Input extension(extension_bytes);

  std::vector<der::Input> ekus;
  EXPECT_TRUE(ParseEKUExtension(extension, &ekus));
  EXPECT_EQ(2u, ekus.size());
  EXPECT_TRUE(HasEKU(ekus, der::Input(kServerAuth)));

  const uint8_t google_oid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79};
  der::Input google(google_oid);
  EXPECT_TRUE(HasEKU(ekus, google));
}

// Test a variety of bad inputs.

// If the extension value has data following the sequence of oids, parsing it
// should fail.
TEST(ExtendedKeyUsageTest, ExtraData) {
  // clang-format off
  const uint8_t extra_data[] = {
      0x30, 0x14,  // SEQUENCE (20 bytes)
      0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
      0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,  // 1.3.6.1.5.5.7.3.1
      0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
      0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02,  // 1.3.6.1.5.5.7.3.2
      // end of SEQUENCE
      0x02, 0x01,  // INTEGER (1 byte)
      0x01  // 1
  };
  // clang-format on

  std::vector<der::Input> ekus;
  EXPECT_FALSE(ParseEKUExtension(der::Input(extra_data), &ekus));
}

// Check that ParseEKUExtension only accepts a sequence containing only oids.
// This test case has an integer in the sequence (which should fail). A key
// difference between this test case and ExtendedKeyUsageTest.ExtraData is where
// the sequence ends - in this test case the integer is still part of the
// sequence, while in ExtendedKeyUsageTest.ExtraData the integer is after the
// sequence.
TEST(ExtendedKeyUsageTest, NotAnOid) {
  // clang-format off
  const uint8_t not_an_oid[] = {
      0x30, 0x0d,  // SEQUENCE (13 bytes)
      0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
      0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,  // 1.3.6.1.5.5.7.3.1
      0x02, 0x01,  // INTEGER (1 byte)
      0x01  // 1
      // end of SEQUENCE
  };
  // clang-format on

  std::vector<der::Input> ekus;
  EXPECT_FALSE(ParseEKUExtension(der::Input(not_an_oid), &ekus));
}

// Checks that the list of oids passed to ParseEKUExtension are in a sequence,
// instead of one or more oid tag-length-values concatenated together.
TEST(ExtendedKeyUsageTest, NotASequence) {
  // clang-format off
  const uint8_t not_a_sequence[] = {
      0x06, 0x08,  // OBJECT IDENTIFIER (8 bytes)
      0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01  // 1.3.6.1.5.5.7.3.1
  };
  // clang-format on

  std::vector<der::Input> ekus;
  EXPECT_FALSE(ParseEKUExtension(der::Input(not_a_sequence), &ekus));
}

// A sequence passed into ParseEKUExtension must have at least one oid in it.
TEST(ExtendedKeyUsageTest, EmptySequence) {
  const uint8_t empty_sequence[] = {0x30, 0x00};  // SEQUENCE (0 bytes)

  std::vector<der::Input> ekus;
  EXPECT_FALSE(ParseEKUExtension(der::Input(empty_sequence), &ekus));
}

// The extension value must not be empty.
TEST(ExtendedKeyUsageTest, EmptyExtension) {
  std::vector<der::Input> ekus;
  EXPECT_FALSE(ParseEKUExtension(der::Input(), &ekus));
}

}  // namespace

}  // namespace net