1/*
2 * Copyright (C) 2017 Metrological Group B.V.
3 * Copyright (C) 2017 Igalia S.L.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "Utilities.h"
29
30#include <mutex>
31#include <wtf/Optional.h>
32#include <wtf/Vector.h>
33
34namespace PAL {
35namespace TASN1 {
36
37static asn1_node asn1Definitions()
38{
39 // Generated with `asn1Parser WebCrypto.asn`.
40
41 static asn1_node s_definitions;
42 static const asn1_static_node s_WebCryptoASN1[] = {
43 { "WebCrypto", 536872976, nullptr },
44 { nullptr, 1073741836, nullptr },
45 { "SubjectPublicKeyInfo", 1610612741, nullptr },
46 { "algorithm", 1073741826, "AlgorithmIdentifier"},
47 { "subjectPublicKey", 6, nullptr },
48 { "AlgorithmIdentifier", 1610612741, nullptr },
49 { "algorithm", 1073741836, nullptr },
50 { "parameters", 541081613, nullptr },
51 { "algorithm", 1, nullptr },
52 { "PrivateKeyInfo", 1610612741, nullptr },
53 { "version", 1073741826, "Version"},
54 { "privateKeyAlgorithm", 1073741826, "PrivateKeyAlgorithmIdentifier"},
55 { "privateKey", 1073741826, "PrivateKey"},
56 { "attributes", 536895490, "Attributes"},
57 { nullptr, 4104, "0"},
58 { "Version", 1073741827, nullptr },
59 { "PrivateKeyAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"},
60 { "PrivateKey", 1073741831, nullptr },
61 { "Attributes", 1610612751, nullptr },
62 { nullptr, 2, "Attribute"},
63 { "Attribute", 1610612741, nullptr },
64 { "type", 1073741836, nullptr },
65 { "values", 2, "AttributeSetValue"},
66 { "AttributeSetValue", 1610612751, nullptr },
67 { nullptr, 13, nullptr },
68 { "ECParameters", 1610612754, nullptr },
69 { "namedCurve", 12, nullptr },
70 { "ECPrivateKey", 1610612741, nullptr },
71 { "version", 1073741827, nullptr },
72 { "privateKey", 1073741831, nullptr },
73 { "parameters", 1610637314, "ECParameters"},
74 { nullptr, 2056, "0"},
75 { "publicKey", 536895494, nullptr },
76 { nullptr, 2056, "1"},
77 { "RSAPublicKey", 1610612741, nullptr },
78 { "modulus", 1073741827, nullptr },
79 { "publicExponent", 3, nullptr },
80 { "RSAPrivateKey", 1610612741, nullptr },
81 { "version", 1073741826, "Version"},
82 { "modulus", 1073741827, nullptr },
83 { "publicExponent", 1073741827, nullptr },
84 { "privateExponent", 1073741827, nullptr },
85 { "prime1", 1073741827, nullptr },
86 { "prime2", 1073741827, nullptr },
87 { "exponent1", 1073741827, nullptr },
88 { "exponent2", 1073741827, nullptr },
89 { "coefficient", 1073741827, nullptr },
90 { "otherPrimeInfos", 16386, "OtherPrimeInfos"},
91 { "OtherPrimeInfos", 1612709899, nullptr },
92 { "MAX", 1074266122, "1"},
93 { nullptr, 2, "OtherPrimeInfo"},
94 { "OtherPrimeInfo", 536870917, nullptr },
95 { "prime", 1073741827, nullptr },
96 { "exponent", 1073741827, nullptr },
97 { "coefficient", 3, nullptr },
98 { nullptr, 0, nullptr }
99 };
100
101 static std::once_flag s_onceFlag;
102 std::call_once(s_onceFlag, [] { asn1_array2tree(s_WebCryptoASN1, &s_definitions, nullptr); });
103
104 return s_definitions;
105}
106
107bool createStructure(const char* elementName, asn1_node* root)
108{
109 int ret = asn1_create_element(asn1Definitions(), elementName, root);
110 return ret == ASN1_SUCCESS;
111}
112
113bool decodeStructure(asn1_node* root, const char* elementName, const Vector<uint8_t>& data)
114{
115 if (!createStructure(elementName, root))
116 return false;
117
118 int dataSize = data.size();
119 int ret = asn1_der_decoding2(root, data.data(), &dataSize, ASN1_DECODE_FLAG_STRICT_DER, nullptr);
120 return ret == ASN1_SUCCESS;
121}
122
123Optional<Vector<uint8_t>> elementData(asn1_node root, const char* elementName)
124{
125 int length = 0;
126 unsigned type = 0;
127 int ret = asn1_read_value_type(root, elementName, nullptr, &length, &type);
128 if (ret != ASN1_MEM_ERROR)
129 return WTF::nullopt;
130
131 if (type == ASN1_ETYPE_BIT_STRING) {
132 if (length % 8)
133 return WTF::nullopt;
134 length /= 8;
135 }
136
137 Vector<uint8_t> data(length);
138 ret = asn1_read_value(root, elementName, data.data(), &length);
139 if (ret != ASN1_SUCCESS)
140 return WTF::nullopt;
141
142 return data;
143}
144
145Optional<Vector<uint8_t>> encodedData(asn1_node root, const char* elementName)
146{
147 int length = 0;
148 int ret = asn1_der_coding(root, elementName, nullptr, &length, nullptr);
149 if (ret != ASN1_MEM_ERROR)
150 return WTF::nullopt;
151
152 Vector<uint8_t> data(length);
153 ret = asn1_der_coding(root, elementName, data.data(), &length, nullptr);
154 if (ret != ASN1_SUCCESS)
155 return WTF::nullopt;
156
157 return data;
158}
159
160bool writeElement(asn1_node root, const char* elementName, const void* data, size_t dataSize)
161{
162 int ret = asn1_write_value(root, elementName, data, dataSize);
163 return ret == ASN1_SUCCESS;
164}
165
166} // namespace TASN1
167} // namespace PAL
168