1 // Copyright 2019 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/ed25519_sign_key_manager.h"
18
19 #include <memory>
20
21 #include "absl/memory/memory.h"
22 #include "absl/status/status.h"
23 #include "absl/strings/str_cat.h"
24 #include "absl/strings/string_view.h"
25 #include "tink/internal/ec_util.h"
26 #include "tink/public_key_sign.h"
27 #include "tink/signature/ed25519_verify_key_manager.h"
28 #include "tink/subtle/ed25519_sign_boringssl.h"
29 #include "tink/util/enums.h"
30 #include "tink/util/errors.h"
31 #include "tink/util/input_stream_util.h"
32 #include "tink/util/protobuf_helper.h"
33 #include "tink/util/secret_data.h"
34 #include "tink/util/status.h"
35 #include "tink/util/statusor.h"
36 #include "tink/util/validation.h"
37 #include "proto/ed25519.pb.h"
38
39 namespace crypto {
40 namespace tink {
41
42 using ::crypto::tink::util::Status;
43 using ::crypto::tink::util::StatusOr;
44 using ::google::crypto::tink::Ed25519KeyFormat;
45 using ::google::crypto::tink::Ed25519PrivateKey;
46
CreateKey(const Ed25519KeyFormat & key_format) const47 StatusOr<Ed25519PrivateKey> Ed25519SignKeyManager::CreateKey(
48 const Ed25519KeyFormat& key_format) const {
49 util::StatusOr<std::unique_ptr<internal::Ed25519Key>> key =
50 internal::NewEd25519Key();
51 if (!key.ok()) {
52 return key.status();
53 }
54
55 Ed25519PrivateKey ed25519_private_key;
56 ed25519_private_key.set_version(get_version());
57 ed25519_private_key.set_key_value((*key)->private_key);
58
59 // Build Ed25519PublicKey.
60 auto ed25519_public_key = ed25519_private_key.mutable_public_key();
61 ed25519_public_key->set_version(get_version());
62 ed25519_public_key->set_key_value((*key)->public_key);
63
64 return ed25519_private_key;
65 }
66
67 StatusOr<std::unique_ptr<PublicKeySign>>
Create(const Ed25519PrivateKey & private_key) const68 Ed25519SignKeyManager::PublicKeySignFactory::Create(
69 const Ed25519PrivateKey& private_key) const {
70 // BoringSSL expects a 64-byte private key which contains the public key as a
71 // suffix.
72 util::SecretData sk = util::SecretDataFromStringView(absl::StrCat(
73 private_key.key_value(), private_key.public_key().key_value()));
74
75 return subtle::Ed25519SignBoringSsl::New(sk);
76 }
77
ValidateKey(const Ed25519PrivateKey & key) const78 Status Ed25519SignKeyManager::ValidateKey(const Ed25519PrivateKey& key) const {
79 Status status = ValidateVersion(key.version(), get_version());
80 if (!status.ok()) return status;
81 if (key.key_value().length() != 32) {
82 return Status(absl::StatusCode::kInvalidArgument,
83 "The ED25519 private key must be 32-bytes long.");
84 }
85 return Ed25519VerifyKeyManager().ValidateKey(key.public_key());
86 }
87
DeriveKey(const Ed25519KeyFormat & key_format,InputStream * input_stream) const88 StatusOr<Ed25519PrivateKey> Ed25519SignKeyManager::DeriveKey(
89 const Ed25519KeyFormat& key_format, InputStream* input_stream) const {
90 util::Status status = ValidateVersion(key_format.version(), get_version());
91 if (!status.ok()) return status;
92
93 util::StatusOr<util::SecretData> randomness =
94 ReadSecretBytesFromStream(kEd25519SecretSeedSize, input_stream);
95 if (!randomness.ok()) {
96 if (randomness.status().code() == absl::StatusCode::kOutOfRange) {
97 return util::Status(
98 absl::StatusCode::kInvalidArgument,
99 "Could not get enough pseudorandomness from input stream");
100 }
101 return randomness.status();
102 }
103 util::StatusOr<std::unique_ptr<internal::Ed25519Key>> key =
104 internal::NewEd25519Key(*randomness);
105
106 Ed25519PrivateKey ed25519_private_key;
107 ed25519_private_key.set_version(get_version());
108 ed25519_private_key.set_key_value((*key)->private_key);
109
110 // Build Ed25519PublicKey.
111 auto ed25519_public_key = ed25519_private_key.mutable_public_key();
112 ed25519_public_key->set_version(get_version());
113 ed25519_public_key->set_key_value((*key)->public_key);
114
115 return ed25519_private_key;
116 }
117
ValidateKeyFormat(const Ed25519KeyFormat & key_format) const118 Status Ed25519SignKeyManager::ValidateKeyFormat(
119 const Ed25519KeyFormat& key_format) const {
120 return util::OkStatus();
121 }
122
123 } // namespace tink
124 } // namespace crypto
125