1 // Copyright 2018 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16
17 #include "tink/signature/signature_pem_keyset_reader.h"
18
19 #include <cstddef>
20 #include <memory>
21 #include <random>
22 #include <string>
23 #include <utility>
24
25 #include "absl/memory/memory.h"
26 #include "absl/status/status.h"
27 #include "absl/strings/str_cat.h"
28 #include "absl/strings/string_view.h"
29 #include "tink/internal/ec_util.h"
30 #include "tink/internal/rsa_util.h"
31 #include "tink/keyset_reader.h"
32 #include "tink/signature/ecdsa_verify_key_manager.h"
33 #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h"
34 #include "tink/signature/rsa_ssa_pkcs1_verify_key_manager.h"
35 #include "tink/signature/rsa_ssa_pss_sign_key_manager.h"
36 #include "tink/signature/rsa_ssa_pss_verify_key_manager.h"
37 #include "tink/subtle/pem_parser_boringssl.h"
38 #include "tink/util/enums.h"
39 #include "tink/util/keyset_util.h"
40 #include "tink/util/secret_data.h"
41 #include "tink/util/status.h"
42 #include "tink/util/statusor.h"
43 #include "proto/common.pb.h"
44 #include "proto/ecdsa.pb.h"
45 #include "proto/rsa_ssa_pkcs1.pb.h"
46 #include "proto/rsa_ssa_pss.pb.h"
47 #include "proto/tink.pb.h"
48
49 namespace crypto {
50 namespace tink {
51
52 using ::google::crypto::tink::EcdsaParams;
53 using ::google::crypto::tink::EcdsaPublicKey;
54 using ::google::crypto::tink::EllipticCurveType;
55 using ::google::crypto::tink::EncryptedKeyset;
56 using ::google::crypto::tink::HashType;
57 using ::google::crypto::tink::KeyData;
58 using ::google::crypto::tink::Keyset;
59 using ::google::crypto::tink::KeyStatusType;
60 using ::google::crypto::tink::OutputPrefixType;
61 using ::google::crypto::tink::RsaSsaPkcs1PrivateKey;
62 using ::google::crypto::tink::RsaSsaPkcs1PublicKey;
63 using ::google::crypto::tink::RsaSsaPssParams;
64 using ::google::crypto::tink::RsaSsaPssPrivateKey;
65 using ::google::crypto::tink::RsaSsaPssPublicKey;
66
67 namespace {
68
69 // Sets the parameters for an RSASSA-PSS key `parameters` given the PEM
70 // parameters `pem_parameters`.
SetRsaSsaPssParameters(const PemKeyParams & pem_parameters,RsaSsaPssParams * parameters)71 util::Status SetRsaSsaPssParameters(const PemKeyParams& pem_parameters,
72 RsaSsaPssParams* parameters) {
73 if (parameters == nullptr) {
74 return util::Status(absl::StatusCode::kInvalidArgument,
75 "Null parameters provided");
76 }
77 parameters->set_mgf1_hash(pem_parameters.hash_type);
78 parameters->set_sig_hash(pem_parameters.hash_type);
79 auto salt_len_or = util::Enums::HashLength(pem_parameters.hash_type);
80 if (!salt_len_or.ok()) return salt_len_or.status();
81 parameters->set_salt_length(salt_len_or.value());
82
83 return util::OkStatus();
84 }
85
86 // Sets the parameters for an ECDSA key `parameters` given the PEM
87 // parameters `pem_parameters`.
SetEcdsaParameters(const PemKeyParams & pem_parameters,EcdsaParams * parameters)88 util::Status SetEcdsaParameters(const PemKeyParams& pem_parameters,
89 EcdsaParams* parameters) {
90 if (parameters == nullptr) {
91 return util::Status(absl::StatusCode::kInvalidArgument,
92 "Null parameters provided");
93 }
94
95 if (pem_parameters.hash_type != HashType::SHA256 ||
96 pem_parameters.key_size_in_bits != 256) {
97 return util::Status(
98 absl::StatusCode::kInvalidArgument,
99 "Only NIST_P256 ECDSA supported. Parameters should contain "
100 "SHA256 and 256 bit key size.");
101 }
102
103 parameters->set_hash_type(pem_parameters.hash_type);
104 parameters->set_curve(EllipticCurveType::NIST_P256);
105
106 switch (pem_parameters.algorithm) {
107 case PemAlgorithm::ECDSA_IEEE: {
108 parameters->set_encoding(
109 google::crypto::tink::EcdsaSignatureEncoding::IEEE_P1363);
110 break;
111 }
112 case PemAlgorithm::ECDSA_DER: {
113 parameters->set_encoding(
114 google::crypto::tink::EcdsaSignatureEncoding::DER);
115 break;
116 }
117 default: {
118 return util::Status(
119 absl::StatusCode::kInvalidArgument,
120 "Only ECDSA supported. The algorithm parameter should be "
121 "ECDSA_IEEE or ECDSA_DER.");
122 }
123 }
124
125 return util::OkStatus();
126 }
127
128 // Creates a new Keyset::Key with ID `key_id`. The key has key data
129 // `key_data`, key type `key_type`, and key material type
130 // `key_material_type`.
NewKeysetKey(uint32_t key_id,absl::string_view key_type,const KeyData::KeyMaterialType & key_material_type,const std::string & key_data)131 Keyset::Key NewKeysetKey(uint32_t key_id, absl::string_view key_type,
132 const KeyData::KeyMaterialType& key_material_type,
133 const std::string& key_data) {
134 Keyset::Key key;
135 // Populate KeyData for the new key.
136 key.set_key_id(key_id);
137 key.set_status(KeyStatusType::ENABLED);
138 // PEM keys don't add any prefix to signatures
139 key.set_output_prefix_type(OutputPrefixType::RAW);
140 KeyData* key_data_proto = key.mutable_key_data();
141 key_data_proto->set_type_url(key_type.data(), key_type.size());
142 key_data_proto->set_value(key_data);
143 key_data_proto->set_key_material_type(key_material_type);
144 return key;
145 }
146
147 // Construct a new RSASSA-PSS key proto from a subtle RSA private key
148 // `private_key_subtle`; the key is assigned version `key_version` and
149 // key paramters `parameters`.
NewRsaSsaPrivateKey(const internal::RsaPrivateKey & private_key_subtle,uint32_t key_version,const PemKeyParams & parameters)150 util::StatusOr<RsaSsaPssPrivateKey> NewRsaSsaPrivateKey(
151 const internal::RsaPrivateKey& private_key_subtle, uint32_t key_version,
152 const PemKeyParams& parameters) {
153 RsaSsaPssPrivateKey private_key_proto;
154
155 // RSA Private key parameters.
156 private_key_proto.set_version(key_version);
157 private_key_proto.set_d(
158 std::string(util::SecretDataAsStringView(private_key_subtle.d)));
159 private_key_proto.set_p(
160 std::string(util::SecretDataAsStringView(private_key_subtle.p)));
161 private_key_proto.set_q(
162 std::string(util::SecretDataAsStringView(private_key_subtle.q)));
163 private_key_proto.set_dp(
164 std::string(util::SecretDataAsStringView(private_key_subtle.dp)));
165 private_key_proto.set_dq(
166 std::string(util::SecretDataAsStringView(private_key_subtle.dq)));
167 private_key_proto.set_crt(
168 std::string(util::SecretDataAsStringView(private_key_subtle.crt)));
169
170 // Inner RSA public key.
171 RsaSsaPssPublicKey* public_key_proto = private_key_proto.mutable_public_key();
172 public_key_proto->set_version(key_version);
173 public_key_proto->set_n(private_key_subtle.n);
174 public_key_proto->set_e(private_key_subtle.e);
175
176 // RSASSA-PSS public key parameters.
177 auto set_parameter_status =
178 SetRsaSsaPssParameters(parameters, public_key_proto->mutable_params());
179 if (!set_parameter_status.ok()) {
180 return set_parameter_status;
181 }
182
183 return private_key_proto;
184 }
185
186 // Construct a new RSASSA-PKCS1 key proto from a subtle RSA private key
187 // `private_key_subtle`; the key is assigned version `key_version` and
188 // key paramters `parameters`.
NewRsaSsaPkcs1PrivateKey(const internal::RsaPrivateKey & private_key_subtle,uint32_t key_version,const PemKeyParams & parameters)189 RsaSsaPkcs1PrivateKey NewRsaSsaPkcs1PrivateKey(
190 const internal::RsaPrivateKey& private_key_subtle, uint32_t key_version,
191 const PemKeyParams& parameters) {
192 RsaSsaPkcs1PrivateKey private_key_proto;
193
194 // RSA Private key parameters.
195 private_key_proto.set_version(key_version);
196 private_key_proto.set_d(
197 std::string(util::SecretDataAsStringView(private_key_subtle.d)));
198 private_key_proto.set_p(
199 std::string(util::SecretDataAsStringView(private_key_subtle.p)));
200 private_key_proto.set_q(
201 std::string(util::SecretDataAsStringView(private_key_subtle.q)));
202 private_key_proto.set_dp(
203 std::string(util::SecretDataAsStringView(private_key_subtle.dp)));
204 private_key_proto.set_dq(
205 std::string(util::SecretDataAsStringView(private_key_subtle.dq)));
206 private_key_proto.set_crt(
207 std::string(util::SecretDataAsStringView(private_key_subtle.crt)));
208
209 // Inner RSA Public key parameters.
210 RsaSsaPkcs1PublicKey* public_key_proto =
211 private_key_proto.mutable_public_key();
212 public_key_proto->set_version(key_version);
213 public_key_proto->set_n(private_key_subtle.n);
214 public_key_proto->set_e(private_key_subtle.e);
215
216 // RSASSA-PKCS1 Public key parameters.
217 public_key_proto->mutable_params()->set_hash_type(parameters.hash_type);
218
219 return private_key_proto;
220 }
221
222 // Adds the PEM-encoded private key `pem_key` to `keyset`.
AddRsaSsaPrivateKey(const PemKey & pem_key,Keyset * keyset)223 util::Status AddRsaSsaPrivateKey(const PemKey& pem_key, Keyset* keyset) {
224 // Try to parse the PEM RSA private key.
225 auto private_key_subtle_or =
226 subtle::PemParser::ParseRsaPrivateKey(pem_key.serialized_key);
227 if (!private_key_subtle_or.ok()) return private_key_subtle_or.status();
228
229 std::unique_ptr<internal::RsaPrivateKey> private_key_subtle =
230 std::move(private_key_subtle_or).value();
231
232 size_t modulus_size = private_key_subtle->n.length() * 8;
233 if (pem_key.parameters.key_size_in_bits != modulus_size) {
234 return util::Status(
235 absl::StatusCode::kInvalidArgument,
236 absl::StrCat("Invalid RSA Key modulus size; found: ", modulus_size,
237 ", expected: ", pem_key.parameters.key_size_in_bits));
238 }
239
240 switch (pem_key.parameters.algorithm) {
241 case PemAlgorithm::RSASSA_PSS: {
242 RsaSsaPssSignKeyManager key_manager;
243 auto private_key_proto_or = NewRsaSsaPrivateKey(
244 *private_key_subtle, key_manager.get_version(), pem_key.parameters);
245 if (!private_key_proto_or.ok()) return private_key_proto_or.status();
246 RsaSsaPssPrivateKey private_key_proto = private_key_proto_or.value();
247
248 // Validate the key.
249 auto key_validation_status = key_manager.ValidateKey(private_key_proto);
250 if (!key_validation_status.ok()) return key_validation_status;
251
252 *keyset->add_key() =
253 NewKeysetKey(GenerateUnusedKeyId(*keyset), key_manager.get_key_type(),
254 key_manager.key_material_type(),
255 private_key_proto.SerializeAsString());
256 break;
257 }
258 case PemAlgorithm::RSASSA_PKCS1: {
259 RsaSsaPkcs1SignKeyManager key_manager;
260 RsaSsaPkcs1PrivateKey private_key_proto = NewRsaSsaPkcs1PrivateKey(
261 *private_key_subtle, key_manager.get_version(), pem_key.parameters);
262
263 // Validate the key.
264 auto key_validation_status = key_manager.ValidateKey(private_key_proto);
265 if (!key_validation_status.ok()) return key_validation_status;
266
267 *keyset->add_key() =
268 NewKeysetKey(GenerateUnusedKeyId(*keyset), key_manager.get_key_type(),
269 key_manager.key_material_type(),
270 private_key_proto.SerializeAsString());
271
272 break;
273 }
274 default:
275 return util::Status(
276 absl::StatusCode::kInvalidArgument,
277 absl::StrCat("Invalid RSA algorithm ", pem_key.parameters.algorithm));
278 }
279
280 return util::OkStatus();
281 }
282 // Parses a given PEM-encoded ECDSA public key `pem_key`, and adds it to the
283 // keyset `keyset`.
AddEcdsaPublicKey(const PemKey & pem_key,Keyset * keyset)284 util::Status AddEcdsaPublicKey(const PemKey& pem_key, Keyset* keyset) {
285 // Parse the PEM string into a ECDSA public key.
286 auto public_key_subtle_or =
287 subtle::PemParser::ParseEcPublicKey(pem_key.serialized_key);
288 if (!public_key_subtle_or.ok()) return public_key_subtle_or.status();
289
290 std::unique_ptr<internal::EcKey> public_key_subtle =
291 std::move(public_key_subtle_or).value();
292
293 EcdsaPublicKey ecdsa_key;
294 EcdsaVerifyKeyManager key_manager;
295
296 // ECDSA Public Key Parameters
297 ecdsa_key.set_x(public_key_subtle->pub_x);
298 ecdsa_key.set_y(public_key_subtle->pub_y);
299 auto set_parameter_status =
300 SetEcdsaParameters(pem_key.parameters, ecdsa_key.mutable_params());
301 if (!set_parameter_status.ok()) return set_parameter_status;
302
303 ecdsa_key.set_version(key_manager.get_version());
304
305 // Validate the key.
306 auto key_validation_status = key_manager.ValidateKey(ecdsa_key);
307 if (!key_validation_status.ok()) return key_validation_status;
308
309 *keyset->add_key() = NewKeysetKey(
310 GenerateUnusedKeyId(*keyset), key_manager.get_key_type(),
311 key_manager.key_material_type(), ecdsa_key.SerializeAsString());
312
313 return util::OkStatus();
314 }
315
316 // Parses a given PEM-encoded RSA public key `pem_key`, and adds it to the
317 // keyset `keyset`.
AddRsaSsaPublicKey(const PemKey & pem_key,Keyset * keyset)318 util::Status AddRsaSsaPublicKey(const PemKey& pem_key, Keyset* keyset) {
319 // Parse the PEM string into a RSA public key.
320 auto public_key_subtle_or =
321 subtle::PemParser::ParseRsaPublicKey(pem_key.serialized_key);
322 if (!public_key_subtle_or.ok()) return public_key_subtle_or.status();
323
324 std::unique_ptr<internal::RsaPublicKey> public_key_subtle =
325 std::move(public_key_subtle_or).value();
326
327 // Check key length is as expected.
328 size_t modulus_size = public_key_subtle->n.length() * 8;
329 if (pem_key.parameters.key_size_in_bits != modulus_size) {
330 return util::Status(
331 absl::StatusCode::kInvalidArgument,
332 absl::StrCat("Invalid RSA Key modulus size; found ", modulus_size,
333 ", expected ", pem_key.parameters.key_size_in_bits));
334 }
335
336 switch (pem_key.parameters.algorithm) {
337 case PemAlgorithm::RSASSA_PSS: {
338 RsaSsaPssPublicKey public_key_proto;
339 RsaSsaPssVerifyKeyManager key_manager;
340
341 // RSA Public key paramters.
342 public_key_proto.set_e(public_key_subtle->e);
343 public_key_proto.set_n(public_key_subtle->n);
344
345 // RSASSA-PSS Public key parameters.
346 auto set_parameter_status = SetRsaSsaPssParameters(
347 pem_key.parameters, public_key_proto.mutable_params());
348 if (!set_parameter_status.ok()) return set_parameter_status;
349 public_key_proto.set_version(key_manager.get_version());
350
351 // Validate the key.
352 auto key_validation_status = key_manager.ValidateKey(public_key_proto);
353 if (!key_validation_status.ok()) return key_validation_status;
354
355 *keyset->add_key() =
356 NewKeysetKey(GenerateUnusedKeyId(*keyset), key_manager.get_key_type(),
357 key_manager.key_material_type(),
358 public_key_proto.SerializeAsString());
359
360 break;
361 }
362 case PemAlgorithm::RSASSA_PKCS1: {
363 RsaSsaPkcs1PublicKey public_key_proto;
364 RsaSsaPkcs1VerifyKeyManager key_manager;
365
366 // RSA Public key paramters.
367 public_key_proto.set_e(public_key_subtle->e);
368 public_key_proto.set_n(public_key_subtle->n);
369
370 // RSASSA-PKCS1 Public key parameters.
371 public_key_proto.mutable_params()->set_hash_type(
372 pem_key.parameters.hash_type);
373 public_key_proto.set_version(key_manager.get_version());
374
375 // Validate the key.
376 auto key_validation_status = key_manager.ValidateKey(public_key_proto);
377 if (!key_validation_status.ok()) return key_validation_status;
378
379 *keyset->add_key() =
380 NewKeysetKey(GenerateUnusedKeyId(*keyset), key_manager.get_key_type(),
381 key_manager.key_material_type(),
382 public_key_proto.SerializeAsString());
383 break;
384 }
385 default:
386 return util::Status(
387 absl::StatusCode::kInvalidArgument,
388 absl::StrCat("Invalid RSA algorithm ", pem_key.parameters.algorithm));
389 }
390 return util::OkStatus();
391 }
392
393 } // namespace
394
Add(const PemKey & pem_serialized_key)395 void SignaturePemKeysetReaderBuilder::Add(const PemKey& pem_serialized_key) {
396 pem_serialized_keys_.push_back(pem_serialized_key);
397 }
398
399 util::StatusOr<std::unique_ptr<KeysetReader>>
Build()400 SignaturePemKeysetReaderBuilder::Build() {
401 if (pem_serialized_keys_.empty()) {
402 return util::Status(absl::StatusCode::kInvalidArgument,
403 "Empty array of PEM-encoded keys");
404 }
405
406 switch (pem_reader_type_) {
407 case PUBLIC_KEY_SIGN: {
408 return absl::WrapUnique<KeysetReader>(
409 new PublicKeySignPemKeysetReader(pem_serialized_keys_));
410 }
411 case PUBLIC_KEY_VERIFY: {
412 return absl::WrapUnique<KeysetReader>(
413 new PublicKeyVerifyPemKeysetReader(pem_serialized_keys_));
414 }
415 }
416 return util::Status(absl::StatusCode::kInvalidArgument,
417 "Unknown pem_reader_type_");
418 }
419
Read()420 util::StatusOr<std::unique_ptr<Keyset>> PublicKeySignPemKeysetReader::Read() {
421 if (pem_serialized_keys_.empty()) {
422 return util::Status(absl::StatusCode::kInvalidArgument,
423 "Empty array of PEM-encoded keys");
424 }
425
426 auto keyset = absl::make_unique<Keyset>();
427 for (const PemKey& pem_key : pem_serialized_keys_) {
428 // Parse and add the new key to the keyset.
429 switch (pem_key.parameters.key_type) {
430 case PemKeyType::PEM_RSA: {
431 auto add_rsassa_pss_status = AddRsaSsaPrivateKey(pem_key, keyset.get());
432 if (!add_rsassa_pss_status.ok()) return add_rsassa_pss_status;
433 break;
434 }
435 default:
436 return util::Status(absl::StatusCode::kUnimplemented,
437 "EC Keys Parsing unimplemented");
438 }
439 }
440
441 // Set the 1st key as primary.
442 keyset->set_primary_key_id(keyset->key(0).key_id());
443
444 return std::move(keyset);
445 }
446
Read()447 util::StatusOr<std::unique_ptr<Keyset>> PublicKeyVerifyPemKeysetReader::Read() {
448 if (pem_serialized_keys_.empty()) {
449 return util::Status(absl::StatusCode::kInvalidArgument,
450 "Empty array of PEM-encoded keys");
451 }
452
453 auto keyset = absl::make_unique<Keyset>();
454 for (const PemKey& pem_key : pem_serialized_keys_) {
455 // Parse and add the new key to the keyset.
456 switch (pem_key.parameters.key_type) {
457 case PemKeyType::PEM_RSA: {
458 auto add_rsassa_pss_status = AddRsaSsaPublicKey(pem_key, keyset.get());
459 if (!add_rsassa_pss_status.ok()) return add_rsassa_pss_status;
460 break;
461 }
462 case PemKeyType::PEM_EC:
463 auto add_ecdsa_status = AddEcdsaPublicKey(pem_key, keyset.get());
464 if (!add_ecdsa_status.ok()) return add_ecdsa_status;
465 }
466 }
467
468 // Set the 1st key as primary.
469 keyset->set_primary_key_id(keyset->key(0).key_id());
470
471 return std::move(keyset);
472 }
473
474 util::StatusOr<std::unique_ptr<EncryptedKeyset>>
ReadEncrypted()475 SignaturePemKeysetReader::ReadEncrypted() {
476 return util::Status(absl::StatusCode::kUnimplemented,
477 "Reading Encrypted PEM is not supported");
478 }
479
480 } // namespace tink
481 } // namespace crypto
482