• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/dilithium_avx2_verify.h"
18 
19 #include <algorithm>
20 #include <cstddef>
21 #include <iterator>
22 #include <memory>
23 #include <string>
24 #include <utility>
25 
26 #include "absl/memory/memory.h"
27 #include "absl/status/status.h"
28 #include "absl/strings/str_format.h"
29 #include "absl/strings/string_view.h"
30 #include "tink/experimental/pqcrypto/signature/subtle/dilithium_key.h"
31 #include "tink/public_key_verify.h"
32 #include "tink/util/statusor.h"
33 
34 extern "C" {
35 #include "third_party/pqclean/crypto_sign/dilithium2/api.h"
36 #include "third_party/pqclean/crypto_sign/dilithium2aes/api.h"
37 #include "third_party/pqclean/crypto_sign/dilithium3/api.h"
38 #include "third_party/pqclean/crypto_sign/dilithium3aes/api.h"
39 #include "third_party/pqclean/crypto_sign/dilithium5/api.h"
40 #include "third_party/pqclean/crypto_sign/dilithium5aes/api.h"
41 }
42 
43 namespace crypto {
44 namespace tink {
45 namespace subtle {
46 
47 // static
New(DilithiumPublicKeyPqclean public_key)48 util::StatusOr<std::unique_ptr<PublicKeyVerify>> DilithiumAvx2Verify::New(
49     DilithiumPublicKeyPqclean public_key) {
50   auto status = internal::CheckFipsCompatibility<DilithiumAvx2Verify>();
51   if (!status.ok()) return status;
52 
53   int32_t key_size = public_key.GetKeyData().size();
54 
55   if (key_size != PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES &&
56       key_size != PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES &&
57       key_size != PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES) {
58     return util::Status(
59         absl::StatusCode::kInvalidArgument,
60         absl::StrFormat("Invalid public key size (%d). "
61                         "The only valid sizes are %d, %d, %d.",
62                         key_size, PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES,
63                         PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES,
64                         PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES));
65   }
66 
67   return {absl::WrapUnique(new DilithiumAvx2Verify(std::move(public_key)))};
68 }
69 
Verify(absl::string_view signature,absl::string_view data) const70 util::Status DilithiumAvx2Verify::Verify(absl::string_view signature,
71                                          absl::string_view data) const {
72   int32_t key_size = public_key_.GetKeyData().size();
73   int result = 1;
74 
75   switch (key_size) {
76     case PQCLEAN_DILITHIUM2_CRYPTO_PUBLICKEYBYTES: {
77       switch (public_key_.GetSeedExpansion()) {
78         case DilithiumSeedExpansion::SEED_EXPANSION_AES: {
79           result = PQCLEAN_DILITHIUM2AES_crypto_sign_verify(
80               reinterpret_cast<const uint8_t *>(signature.data()),
81               signature.size(), reinterpret_cast<const uint8_t *>(data.data()),
82               data.size(),
83               reinterpret_cast<const uint8_t *>(
84                   public_key_.GetKeyData().data()));
85 
86           break;
87         }
88         case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: {
89           result = PQCLEAN_DILITHIUM2_crypto_sign_verify(
90               reinterpret_cast<const uint8_t *>(signature.data()),
91               signature.size(), reinterpret_cast<const uint8_t *>(data.data()),
92               data.size(),
93               reinterpret_cast<const uint8_t *>(
94                   public_key_.GetKeyData().data()));
95           break;
96         }
97         default: {
98           return util::Status(absl::StatusCode::kInternal,
99                               "Invalid seed expansion.");
100         }
101       }
102       break;
103     }
104     case PQCLEAN_DILITHIUM3_CRYPTO_PUBLICKEYBYTES: {
105       switch (public_key_.GetSeedExpansion()) {
106         case DilithiumSeedExpansion::SEED_EXPANSION_AES: {
107           result = PQCLEAN_DILITHIUM3AES_crypto_sign_verify(
108               reinterpret_cast<const uint8_t *>(signature.data()),
109               signature.size(), reinterpret_cast<const uint8_t *>(data.data()),
110               data.size(),
111               reinterpret_cast<const uint8_t *>(
112                   public_key_.GetKeyData().data()));
113           break;
114         }
115         case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: {
116           result = PQCLEAN_DILITHIUM3_crypto_sign_verify(
117               reinterpret_cast<const uint8_t *>(signature.data()),
118               signature.size(), reinterpret_cast<const uint8_t *>(data.data()),
119               data.size(),
120               reinterpret_cast<const uint8_t *>(
121                   public_key_.GetKeyData().data()));
122           break;
123         }
124         default: {
125           return util::Status(absl::StatusCode::kInternal,
126                               "Invalid seed expansion.");
127         }
128       }
129       break;
130     }
131     case PQCLEAN_DILITHIUM5_CRYPTO_PUBLICKEYBYTES: {
132       switch (public_key_.GetSeedExpansion()) {
133         case DilithiumSeedExpansion::SEED_EXPANSION_AES: {
134           result = PQCLEAN_DILITHIUM5AES_crypto_sign_verify(
135               reinterpret_cast<const uint8_t *>(signature.data()),
136               signature.size(), reinterpret_cast<const uint8_t *>(data.data()),
137               data.size(),
138               reinterpret_cast<const uint8_t *>(
139                   public_key_.GetKeyData().data()));
140           break;
141         }
142         case DilithiumSeedExpansion::SEED_EXPANSION_SHAKE: {
143           result = PQCLEAN_DILITHIUM5_crypto_sign_verify(
144               reinterpret_cast<const uint8_t *>(signature.data()),
145               signature.size(), reinterpret_cast<const uint8_t *>(data.data()),
146               data.size(),
147               reinterpret_cast<const uint8_t *>(
148                   public_key_.GetKeyData().data()));
149           break;
150         }
151         default: {
152           return util::Status(absl::StatusCode::kInternal,
153                               "Invalid seed expansion.");
154         }
155       }
156       break;
157     }
158     default:
159       return util::Status(absl::StatusCode::kInternal, "Invalid keysize.");
160   }
161 
162   if (result != 0) {
163     return util::Status(absl::StatusCode::kInvalidArgument,
164                         "Signature is not valid.");
165   }
166 
167   return util::OkStatus();
168 }
169 
170 }  // namespace subtle
171 }  // namespace tink
172 }  // namespace crypto
173