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/jwt/internal/raw_jwt_hmac_key_manager.h"
18
19 #include <map>
20
21 #include "absl/status/status.h"
22 #include "absl/strings/string_view.h"
23 #include "tink/mac.h"
24 #include "tink/subtle/hmac_boringssl.h"
25 #include "tink/subtle/random.h"
26 #include "tink/util/enums.h"
27 #include "tink/util/errors.h"
28 #include "tink/util/input_stream_util.h"
29 #include "tink/util/protobuf_helper.h"
30 #include "tink/util/status.h"
31 #include "tink/util/statusor.h"
32 #include "tink/util/validation.h"
33 #include "proto/common.pb.h"
34 #include "proto/jwt_hmac.pb.h"
35 #include "proto/tink.pb.h"
36
37 namespace crypto {
38 namespace tink {
39 namespace jwt_internal {
40
41 using crypto::tink::util::Status;
42 using crypto::tink::util::StatusOr;
43 using google::crypto::tink::JwtHmacAlgorithm;
44 using google::crypto::tink::JwtHmacKey;
45 using google::crypto::tink::JwtHmacKeyFormat;
46
47 namespace {
48
MinimumKeySize(const JwtHmacAlgorithm & algorithm)49 StatusOr<int> MinimumKeySize(const JwtHmacAlgorithm& algorithm) {
50 switch (algorithm) {
51 case JwtHmacAlgorithm::HS256:
52 return 32;
53 case JwtHmacAlgorithm::HS384:
54 return 48;
55 case JwtHmacAlgorithm::HS512:
56 return 64;
57 default:
58 return Status(absl::StatusCode::kInvalidArgument,
59 "Unsupported algorithm.");
60 }
61 }
62
63 } // namespace
64
CreateKey(const JwtHmacKeyFormat & jwt_hmac_key_format) const65 StatusOr<JwtHmacKey> RawJwtHmacKeyManager::CreateKey(
66 const JwtHmacKeyFormat& jwt_hmac_key_format) const {
67 JwtHmacKey jwt_hmac_key;
68 jwt_hmac_key.set_version(get_version());
69 jwt_hmac_key.set_algorithm(jwt_hmac_key_format.algorithm());
70 jwt_hmac_key.set_key_value(
71 subtle::Random::GetRandomBytes(jwt_hmac_key_format.key_size()));
72 return jwt_hmac_key;
73 }
74
DeriveKey(const JwtHmacKeyFormat & jwt_hmac_key_format,InputStream * input_stream) const75 StatusOr<JwtHmacKey> RawJwtHmacKeyManager::DeriveKey(
76 const JwtHmacKeyFormat& jwt_hmac_key_format,
77 InputStream* input_stream) const {
78 return util::Status(absl::StatusCode::kUnimplemented,
79 "RawJwtHmacKeyManager::DeriveKey is not implemented");
80 }
81
ValidateKey(const JwtHmacKey & key) const82 Status RawJwtHmacKeyManager::ValidateKey(const JwtHmacKey& key) const {
83 Status status = ValidateVersion(key.version(), get_version());
84 if (!status.ok()) return status;
85 StatusOr<int> min_key_size = MinimumKeySize(key.algorithm());
86 if (!min_key_size.ok()) {
87 return min_key_size.status();
88 }
89 if (key.key_value().size() < *min_key_size) {
90 return util::Status(absl::StatusCode::kInvalidArgument,
91 "Invalid JwtHmacKey: key_value is too short.");
92 }
93 return util::OkStatus();
94 }
95
96 // static
ValidateKeyFormat(const JwtHmacKeyFormat & key_format) const97 Status RawJwtHmacKeyManager::ValidateKeyFormat(
98 const JwtHmacKeyFormat& key_format) const {
99 StatusOr<int> min_key_size = MinimumKeySize(key_format.algorithm());
100 if (!min_key_size.ok()) {
101 return min_key_size.status();
102 }
103 if (key_format.key_size() < *min_key_size) {
104 return util::Status(absl::StatusCode::kInvalidArgument,
105 "Invalid HmacKeyFormat: key_size is too small.");
106 }
107 return util::OkStatus();
108 }
109
110 } // namespace jwt_internal
111 } // namespace tink
112 } // namespace crypto
113