Packages
hackney
2.0.1
4.7.2
4.7.1
4.7.0
4.6.1
4.6.0
4.5.2
4.5.1
4.5.0
4.4.5
4.4.3
4.4.2
4.4.1
4.4.0
4.3.0
4.2.3
4.2.2
4.2.1
4.2.0
4.1.0
4.0.3
4.0.2
4.0.1
4.0.0
3.2.1
3.2.0
3.1.2
3.1.1
3.1.0
3.0.3
3.0.2
3.0.1
3.0.0
retired
2.0.1
2.0.0
2.0.0-beta.1
1.25.0
1.24.1
1.24.0
1.23.0
1.22.0
1.21.0
1.20.1
1.20.0
1.19.1
1.19.0
1.18.2
1.18.1
1.18.0
1.17.4
1.17.3
1.17.2
1.17.1
1.17.0
1.16.0
1.15.2
1.15.1
1.15.0
1.14.3
1.14.2
1.14.0
1.13.0
1.12.1
1.12.0
1.11.0
1.10.1
1.10.0
1.9.0
1.8.6
1.8.5
1.8.4
1.8.3
1.8.2
1.8.0
1.7.1
1.7.0
1.6.6
retired
1.6.5
1.6.4
retired
1.6.3
1.6.2
1.6.1
1.6.0
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.10
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.0
1.0.6
1.0.5
1.0.2
1.0.1
0.15.2
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
Simple HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
c_src/boringssl/crypto/fipsmodule/aes/key_wrap.cc.inc
// Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <openssl/aes.h>
#include <assert.h>
#include <limits.h>
#include <string.h>
#include <openssl/mem.h>
#include "../bcm_interface.h"
#include "../../internal.h"
#include "../service_indicator/internal.h"
// kDefaultIV is the default IV value given in RFC 3394, 2.2.3.1.
static const uint8_t kDefaultIV[] = {
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
};
static const unsigned kBound = 6;
int AES_wrap_key(const AES_KEY *key, const uint8_t *iv, uint8_t *out,
const uint8_t *in, size_t in_len) {
// See RFC 3394, section 2.2.1. Additionally, note that section 2 requires the
// plaintext be at least two 8-byte blocks.
if (in_len > INT_MAX - 8 || in_len < 16 || in_len % 8 != 0) {
return -1;
}
if (iv == nullptr) {
iv = kDefaultIV;
}
OPENSSL_memmove(out + 8, in, in_len);
uint8_t A[AES_BLOCK_SIZE];
OPENSSL_memcpy(A, iv, 8);
size_t n = in_len / 8;
for (unsigned j = 0; j < kBound; j++) {
for (size_t i = 1; i <= n; i++) {
OPENSSL_memcpy(A + 8, out + 8 * i, 8);
BCM_aes_encrypt(A, A, key);
uint32_t t = (uint32_t)(n * j + i);
A[7] ^= t & 0xff;
A[6] ^= (t >> 8) & 0xff;
A[5] ^= (t >> 16) & 0xff;
A[4] ^= (t >> 24) & 0xff;
OPENSSL_memcpy(out + 8 * i, A + 8, 8);
}
}
OPENSSL_memcpy(out, A, 8);
FIPS_service_indicator_update_state();
return (int)in_len + 8;
}
// aes_unwrap_key_inner performs steps one and two from
// https://tools.ietf.org/html/rfc3394#section-2.2.2
static int aes_unwrap_key_inner(const AES_KEY *key, uint8_t *out,
uint8_t out_iv[8], const uint8_t *in,
size_t in_len) {
// See RFC 3394, section 2.2.2. Additionally, note that section 2 requires the
// plaintext be at least two 8-byte blocks, so the ciphertext must be at least
// three blocks.
if (in_len > INT_MAX || in_len < 24 || in_len % 8 != 0) {
return 0;
}
uint8_t A[AES_BLOCK_SIZE];
OPENSSL_memcpy(A, in, 8);
OPENSSL_memmove(out, in + 8, in_len - 8);
size_t n = (in_len / 8) - 1;
for (unsigned j = kBound - 1; j < kBound; j--) {
for (size_t i = n; i > 0; i--) {
uint32_t t = (uint32_t)(n * j + i);
A[7] ^= t & 0xff;
A[6] ^= (t >> 8) & 0xff;
A[5] ^= (t >> 16) & 0xff;
A[4] ^= (t >> 24) & 0xff;
OPENSSL_memcpy(A + 8, out + 8 * (i - 1), 8);
BCM_aes_decrypt(A, A, key);
OPENSSL_memcpy(out + 8 * (i - 1), A + 8, 8);
}
}
memcpy(out_iv, A, 8);
return 1;
}
int AES_unwrap_key(const AES_KEY *key, const uint8_t *iv, uint8_t *out,
const uint8_t *in, size_t in_len) {
uint8_t calculated_iv[8];
if (!aes_unwrap_key_inner(key, out, calculated_iv, in, in_len)) {
return -1;
}
if (iv == nullptr) {
iv = kDefaultIV;
}
if (CRYPTO_memcmp(calculated_iv, iv, 8) != 0) {
return -1;
}
FIPS_service_indicator_update_state();
return (int)in_len - 8;
}
// kPaddingConstant is used in Key Wrap with Padding. See
// https://tools.ietf.org/html/rfc5649#section-3
static const uint8_t kPaddingConstant[4] = {0xa6, 0x59, 0x59, 0xa6};
int AES_wrap_key_padded(const AES_KEY *key, uint8_t *out, size_t *out_len,
size_t max_out, const uint8_t *in, size_t in_len) {
// See https://tools.ietf.org/html/rfc5649#section-4.1
const uint64_t in_len64 = in_len;
const size_t padded_len = (in_len + 7) & ~7;
*out_len = 0;
if (in_len == 0 || in_len64 > 0xffffffffu || in_len + 7 < in_len ||
padded_len + 8 < padded_len || max_out < padded_len + 8) {
return 0;
}
uint8_t block[AES_BLOCK_SIZE];
memcpy(block, kPaddingConstant, sizeof(kPaddingConstant));
CRYPTO_store_u32_be(block + 4, (uint32_t)in_len);
if (in_len <= 8) {
memset(block + 8, 0, 8);
memcpy(block + 8, in, in_len);
BCM_aes_encrypt(block, out, key);
*out_len = AES_BLOCK_SIZE;
return 1;
}
uint8_t *padded_in = reinterpret_cast<uint8_t *>(OPENSSL_malloc(padded_len));
if (padded_in == nullptr) {
return 0;
}
assert(padded_len >= 8);
memset(padded_in + padded_len - 8, 0, 8);
memcpy(padded_in, in, in_len);
FIPS_service_indicator_lock_state();
const int ret = AES_wrap_key(key, block, out, padded_in, padded_len);
FIPS_service_indicator_unlock_state();
OPENSSL_free(padded_in);
if (ret < 0) {
return 0;
}
*out_len = ret;
FIPS_service_indicator_update_state();
return 1;
}
int AES_unwrap_key_padded(const AES_KEY *key, uint8_t *out, size_t *out_len,
size_t max_out, const uint8_t *in, size_t in_len) {
*out_len = 0;
if (in_len < AES_BLOCK_SIZE || max_out < in_len - 8) {
return 0;
}
uint8_t iv[8];
if (in_len == AES_BLOCK_SIZE) {
uint8_t block[AES_BLOCK_SIZE];
BCM_aes_decrypt(in, block, key);
memcpy(iv, block, sizeof(iv));
memcpy(out, block + 8, 8);
} else if (!aes_unwrap_key_inner(key, out, iv, in, in_len)) {
return 0;
}
assert(in_len % 8 == 0);
crypto_word_t ok = constant_time_eq_int(
CRYPTO_memcmp(iv, kPaddingConstant, sizeof(kPaddingConstant)), 0);
const size_t claimed_len = CRYPTO_load_u32_be(iv + 4);
ok &= ~constant_time_is_zero_w(claimed_len);
ok &= constant_time_eq_w((claimed_len - 1) >> 3, (in_len - 9) >> 3);
// Check that padding bytes are all zero.
for (size_t i = in_len - 15; i < in_len - 8; i++) {
ok &= constant_time_is_zero_w(constant_time_ge_8(i, claimed_len) & out[i]);
}
*out_len = constant_time_select_w(ok, claimed_len, 0);
const int ret = ok & 1;
if (ret) {
FIPS_service_indicator_update_state();
}
return ret;
}