xref: /aosp_15_r20/external/tink/cc/signature/ed25519_sign_key_manager.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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