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