1 // Copyright 2021 Google LLC
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/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h"
18
19 #include <string>
20 #include <utility>
21
22 #include "absl/memory/memory.h"
23 #include "absl/status/status.h"
24 #include "absl/strings/str_format.h"
25 #include "tink/experimental/pqcrypto/signature/subtle/sphincs_helper_pqclean.h"
26 #include "tink/util/secret_data.h"
27 #include "tink/util/status.h"
28 #include "tink/util/statusor.h"
29
30 extern "C" {
31 #include "third_party/pqclean/crypto_sign/falcon-1024/api.h"
32 #include "third_party/pqclean/crypto_sign/falcon-512/api.h"
33 }
34
35 namespace crypto {
36 namespace tink {
37 namespace subtle {
38
39 // static
NewPrivateKey(const util::SecretData & key_data)40 util::StatusOr<FalconPrivateKeyPqclean> FalconPrivateKeyPqclean::NewPrivateKey(
41 const util::SecretData& key_data) {
42 util::Status status = ValidateFalconPrivateKeySize(key_data.size());
43 if (!status.ok()) {
44 return status;
45 }
46
47 return FalconPrivateKeyPqclean(key_data);
48 }
49
50 // static
NewPublicKey(absl::string_view key_data)51 util::StatusOr<FalconPublicKeyPqclean> FalconPublicKeyPqclean::NewPublicKey(
52 absl::string_view key_data) {
53 util::Status status = ValidateFalconPublicKeySize(key_data.size());
54 if (!status.ok()) {
55 return status;
56 }
57
58 return FalconPublicKeyPqclean(key_data);
59 }
60
GenerateFalconKeyPair(int32_t private_key_size)61 crypto::tink::util::StatusOr<FalconKeyPair> GenerateFalconKeyPair(
62 int32_t private_key_size) {
63 std::string public_key;
64 std::string private_key;
65
66 switch (private_key_size) {
67 // Falcon512.
68 case kFalcon512PrivateKeySize: {
69 private_key.resize(private_key_size);
70 public_key.resize(kFalcon512PublicKeySize);
71 PQCLEAN_FALCON512_crypto_sign_keypair(
72 reinterpret_cast<uint8_t*>(public_key.data()),
73 reinterpret_cast<uint8_t*>(private_key.data()));
74 break;
75 }
76 // Falcon1024.
77 case kFalcon1024PrivateKeySize: {
78 private_key.resize(private_key_size);
79 public_key.resize(kFalcon1024PublicKeySize);
80 PQCLEAN_FALCON1024_crypto_sign_keypair(
81 reinterpret_cast<uint8_t*>(public_key.data()),
82 reinterpret_cast<uint8_t*>(private_key.data()));
83 break;
84 }
85 // Invalid key size.
86 default: {
87 return util::Status(
88 absl::StatusCode::kInvalidArgument,
89 absl::StrFormat("Invalid private key size (%d). "
90 "The only valid sizes are %d, %d",
91 private_key_size, kFalcon512PrivateKeySize,
92 kFalcon1024PrivateKeySize));
93 }
94 }
95
96 util::SecretData private_key_data =
97 util::SecretDataFromStringView(private_key);
98
99 util::StatusOr<FalconPrivateKeyPqclean> falcon_private_key =
100 FalconPrivateKeyPqclean::NewPrivateKey(private_key_data);
101 util::StatusOr<FalconPublicKeyPqclean> falcon_public_key =
102 FalconPublicKeyPqclean::NewPublicKey(public_key);
103
104 if (!falcon_private_key.ok() || !falcon_public_key.ok()) {
105 return util::Status(absl::StatusCode::kInternal, "Key generation failed.");
106 }
107
108 FalconKeyPair key_pair(*falcon_private_key, *falcon_public_key);
109
110 return key_pair;
111 }
112
ValidateFalconPrivateKeySize(int32_t key_size)113 crypto::tink::util::Status ValidateFalconPrivateKeySize(int32_t key_size) {
114 switch (key_size) {
115 case kFalcon512PrivateKeySize:
116 case kFalcon1024PrivateKeySize:
117 return util::OkStatus();
118 default:
119 return util::Status(absl::StatusCode::kInvalidArgument,
120 absl::StrFormat("Invalid private key size (%d). "
121 "The only valid sizes are %d, %d",
122 key_size, kFalcon512PrivateKeySize,
123 kFalcon1024PrivateKeySize));
124 }
125 }
126
ValidateFalconPublicKeySize(int32_t key_size)127 crypto::tink::util::Status ValidateFalconPublicKeySize(int32_t key_size) {
128 switch (key_size) {
129 case kFalcon512PublicKeySize:
130 case kFalcon1024PublicKeySize:
131 return util::OkStatus();
132 default:
133 return util::Status(absl::StatusCode::kInvalidArgument,
134 absl::StrFormat("Invalid public key size (%d). "
135 "The only valid sizes are %d, %d",
136 key_size, kFalcon512PublicKeySize,
137 kFalcon1024PublicKeySize));
138 }
139 }
140
141 } // namespace subtle
142 } // namespace tink
143 } // namespace crypto
144