xref: /aosp_15_r20/external/tink/cc/experimental/pqcrypto/signature/subtle/sphincs_subtle_utils.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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/sphincs_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 namespace crypto {
31 namespace tink {
32 namespace subtle {
33 
GenerateSphincsKeyPair(SphincsParamsPqclean params)34 crypto::tink::util::StatusOr<SphincsKeyPair> GenerateSphincsKeyPair(
35     SphincsParamsPqclean params) {
36   // Check if parameters are valid.
37   util::Status valid_parameters = ValidateParams(params);
38   if (!valid_parameters.ok()) {
39     return valid_parameters;
40   }
41 
42   util::StatusOr<int32> key_size_index =
43       SphincsKeySizeToIndex(params.private_key_size);
44   if (!key_size_index.ok()) {
45     return key_size_index.status();
46   }
47 
48   std::string public_key;
49   std::string private_key;
50   private_key.resize(params.private_key_size);
51 
52   const SphincsHelperPqclean &sphincs_helper_pqclean =
53       GetSphincsHelperPqclean(params.hash_type, params.variant, *key_size_index,
54                               params.sig_length_type);
55   public_key.resize(sphincs_helper_pqclean.GetPublicKeySize());
56 
57   if (0 != sphincs_helper_pqclean.Keygen(
58                reinterpret_cast<uint8_t *>(public_key.data()),
59                reinterpret_cast<uint8_t *>(private_key.data()))) {
60     return util::Status(absl::StatusCode::kInternal, "Key generation failed.");
61   }
62 
63   util::SecretData private_key_data =
64       util::SecretDataFromStringView(private_key);
65 
66   SphincsKeyPair key_pair(SphincsPrivateKeyPqclean{private_key_data, params},
67                           SphincsPublicKeyPqclean{public_key, params});
68 
69   return key_pair;
70 }
71 
ValidatePrivateKeySize(int32 key_size)72 crypto::tink::util::Status ValidatePrivateKeySize(int32 key_size) {
73   switch (key_size) {
74     case kSphincsPrivateKeySize64:
75     case kSphincsPrivateKeySize96:
76     case kSphincsPrivateKeySize128:
77       return util::OkStatus();
78     default:
79       return util::Status(
80           absl::StatusCode::kInvalidArgument,
81           absl::StrFormat("Invalid private key size (%d). "
82                           "The only valid sizes are %d, %d, %d.",
83                           key_size, kSphincsPrivateKeySize64,
84                           kSphincsPrivateKeySize96, kSphincsPrivateKeySize128));
85   }
86 }
87 
ValidatePublicKeySize(int32 key_size)88 crypto::tink::util::Status ValidatePublicKeySize(int32 key_size) {
89   switch (key_size) {
90     case kSphincsPublicKeySize32:
91     case kSphincsPublicKeySize48:
92     case kSphincsPublicKeySize64:
93       return util::OkStatus();
94     default:
95       return util::Status(
96           absl::StatusCode::kInvalidArgument,
97           absl::StrFormat("Invalid private key size (%d). "
98                           "The only valid sizes are %d, %d, %d.",
99                           key_size, kSphincsPublicKeySize32,
100                           kSphincsPublicKeySize48, kSphincsPublicKeySize64));
101   }
102 }
103 
SphincsKeySizeToIndex(int32 key_size)104 crypto::tink::util::StatusOr<int32> SphincsKeySizeToIndex(int32 key_size) {
105   switch (key_size) {
106     case kSphincsPrivateKeySize64:
107       return 0;
108     case kSphincsPrivateKeySize96:
109       return 1;
110     case kSphincsPrivateKeySize128:
111       return 2;
112     default:
113       return util::Status(absl::StatusCode::kInvalidArgument,
114                           "Invalid key size");
115   }
116 }
117 
ValidateParams(SphincsParamsPqclean params)118 crypto::tink::util::Status ValidateParams(SphincsParamsPqclean params) {
119   switch (params.hash_type) {
120     case SphincsHashType::HARAKA:
121     case SphincsHashType::SHA256:
122     case SphincsHashType::SHAKE256: {
123       break;
124     }
125     default: {
126       return util::Status(absl::StatusCode::kInvalidArgument,
127                           "Invalid hash type");
128     }
129   }
130 
131   switch (params.variant) {
132     case SphincsVariant::ROBUST:
133     case SphincsVariant::SIMPLE: {
134       break;
135     }
136     default: {
137       return util::Status(absl::StatusCode::kInvalidArgument,
138                           "Invalid variant");
139     }
140   }
141 
142   switch (params.sig_length_type) {
143     case SphincsSignatureType::FAST_SIGNING:
144     case SphincsSignatureType::SMALL_SIGNATURE: {
145       break;
146     }
147     default: {
148       return util::Status(absl::StatusCode::kInvalidArgument,
149                           "Invalid signature type");
150     }
151   }
152 
153   return ValidatePrivateKeySize(params.private_key_size);
154 }
155 
156 }  // namespace subtle
157 }  // namespace tink
158 }  // namespace crypto
159