xref: /aosp_15_r20/external/tink/cc/util/validation.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2017 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/util/validation.h"
18 
19 #include "absl/status/status.h"
20 #include "tink/util/errors.h"
21 #include "tink/util/status.h"
22 #include "proto/tink.pb.h"
23 
24 using google::crypto::tink::KeyData;
25 using google::crypto::tink::Keyset;
26 using google::crypto::tink::KeyStatusType;
27 
28 namespace crypto {
29 namespace tink {
30 
ValidateAesKeySize(uint32_t key_size)31 util::Status ValidateAesKeySize(uint32_t key_size) {
32   if (key_size != 16 && key_size != 32) {
33     return ToStatusF(absl::StatusCode::kInvalidArgument,
34                      "AES key has %d bytes; supported sizes: 16 or 32 bytes.",
35                      key_size);
36   }
37   return util::OkStatus();
38 }
39 
ValidateKey(const Keyset::Key & key)40 util::Status ValidateKey(const Keyset::Key& key) {
41   if (!key.has_key_data()) {
42     return ToStatusF(absl::StatusCode::kInvalidArgument,
43                      "key %d, has no key data", key.key_id());
44   }
45 
46   if (key.output_prefix_type() ==
47       google::crypto::tink::OutputPrefixType::UNKNOWN_PREFIX) {
48     return ToStatusF(absl::StatusCode::kInvalidArgument,
49                      "key %d has unknown prefix", key.key_id());
50   }
51 
52   if (key.status() == google::crypto::tink::KeyStatusType::UNKNOWN_STATUS) {
53     return ToStatusF(absl::StatusCode::kInvalidArgument,
54                      "key %d has unknown status", key.key_id());
55   }
56   return util::OkStatus();
57 }
58 
ValidateKeyset(const Keyset & keyset)59 util::Status ValidateKeyset(const Keyset& keyset) {
60   if (keyset.key_size() < 1) {
61     return util::Status(absl::StatusCode::kInvalidArgument,
62                         "A valid keyset must contain at least one key.");
63   }
64 
65   uint32_t primary_key_id = keyset.primary_key_id();
66   bool has_primary_key = false;
67   bool contains_only_public_key_material = true;
68   int enabled_keys = 0;
69 
70   for (int i = 0; i < keyset.key_size(); i++) {
71     const Keyset::Key& key = keyset.key(i);
72 
73 
74     if (key.status() != KeyStatusType::ENABLED) {
75       continue;
76     }
77     enabled_keys += 1;
78 
79     auto validation_result = ValidateKey(key);
80     if (!validation_result.ok()) {
81       return validation_result;
82     }
83 
84     if (key.status() == KeyStatusType::ENABLED &&
85         key.key_id() == primary_key_id) {
86       if (has_primary_key) {
87         return util::Status(absl::StatusCode::kInvalidArgument,
88                             "keyset contains multiple primary keys");
89       }
90       has_primary_key = true;
91     }
92 
93     if (key.key_data().key_material_type() != KeyData::ASYMMETRIC_PUBLIC) {
94       contains_only_public_key_material = false;
95     }
96   }
97 
98   if (enabled_keys == 0) {
99     return util::Status(absl::StatusCode::kInvalidArgument,
100                         "keyset must contain at least one ENABLED key");
101   }
102 
103   // A public key can be used for verification without being set as the primary
104   // key. Therefore, it is okay to have a keyset that contains public but
105   // doesn't have a primary key set.
106   if (!has_primary_key && !contains_only_public_key_material) {
107     return util::Status(absl::StatusCode::kInvalidArgument,
108                         "keyset doesn't contain a valid primary key");
109   }
110 
111   return util::OkStatus();
112 }
113 
ValidateVersion(uint32_t candidate,uint32_t max_expected)114 util::Status ValidateVersion(uint32_t candidate, uint32_t max_expected) {
115   if (candidate > max_expected) {
116     return ToStatusF(absl::StatusCode::kInvalidArgument,
117                      "Key has version '%d'; "
118                      "only keys with version in range [0..%d] are supported.",
119                      candidate, max_expected);
120   }
121   return util::OkStatus();
122 }
123 
124 }  // namespace tink
125 }  // namespace crypto
126