Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"
This reverts commit 15b7df8ef1.
This commit is contained in:
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
#include <vapours/crypto/crypto_cmac_generator.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
class Aes128CmacGenerator {
|
||||
NON_COPYABLE(Aes128CmacGenerator);
|
||||
NON_MOVEABLE(Aes128CmacGenerator);
|
||||
public:
|
||||
static constexpr size_t MacSize = AesEncryptor128::BlockSize;
|
||||
private:
|
||||
AesEncryptor128 m_aes;
|
||||
CmacGenerator<AesEncryptor128> m_cmac_generator;
|
||||
public:
|
||||
Aes128CmacGenerator() { /* ... */ }
|
||||
|
||||
void Initialize(const void *key, size_t key_size) {
|
||||
AMS_ASSERT(key_size == AesEncryptor128::KeySize);
|
||||
|
||||
m_aes.Initialize(key, key_size);
|
||||
m_cmac_generator.Initialize(std::addressof(m_aes));
|
||||
}
|
||||
|
||||
void Update(const void *data, size_t size) {
|
||||
m_cmac_generator.Update(data, size);
|
||||
}
|
||||
|
||||
void GetMac(void *dst, size_t size) {
|
||||
m_cmac_generator.GetMac(dst, size);
|
||||
}
|
||||
};
|
||||
|
||||
ALWAYS_INLINE void GenerateAes128Cmac(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size) {
|
||||
Aes128CmacGenerator cmac_generator;
|
||||
|
||||
cmac_generator.Initialize(key, key_size);
|
||||
cmac_generator.Update(data, data_size);
|
||||
cmac_generator.GetMac(dst, dst_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
#include <vapours/crypto/crypto_cbc_encryptor.hpp>
|
||||
#include <vapours/crypto/crypto_cbc_decryptor.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<template<typename> typename _CbcImpl, typename _AesImpl>
|
||||
class AesCbcCryptor {
|
||||
NON_COPYABLE(AesCbcCryptor);
|
||||
NON_MOVEABLE(AesCbcCryptor);
|
||||
private:
|
||||
using AesImpl = _AesImpl;
|
||||
using CbcImpl = _CbcImpl<AesImpl>;
|
||||
public:
|
||||
static constexpr size_t KeySize = AesImpl::KeySize;
|
||||
static constexpr size_t BlockSize = CbcImpl::BlockSize;
|
||||
static constexpr size_t IvSize = CbcImpl::BlockSize;
|
||||
private:
|
||||
AesImpl m_aes_impl;
|
||||
CbcImpl m_cbc_impl;
|
||||
public:
|
||||
AesCbcCryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const void *key, size_t key_size, const void *iv, size_t iv_size) {
|
||||
AMS_ASSERT(key_size == KeySize);
|
||||
AMS_ASSERT(iv_size == IvSize);
|
||||
|
||||
m_aes_impl.Initialize(key, key_size);
|
||||
m_cbc_impl.Initialize(std::addressof(m_aes_impl), iv, iv_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_cbc_impl.Update(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
size_t GetBufferedDataSize() const {
|
||||
return m_cbc_impl.GetBufferedDataSize();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using Aes128CbcEncryptor = impl::AesCbcCryptor<CbcEncryptor, AesEncryptor128>;
|
||||
using Aes192CbcEncryptor = impl::AesCbcCryptor<CbcEncryptor, AesEncryptor192>;
|
||||
using Aes256CbcEncryptor = impl::AesCbcCryptor<CbcEncryptor, AesEncryptor256>;
|
||||
|
||||
using Aes128CbcDecryptor = impl::AesCbcCryptor<CbcDecryptor, AesDecryptor128>;
|
||||
using Aes192CbcDecryptor = impl::AesCbcCryptor<CbcDecryptor, AesDecryptor192>;
|
||||
using Aes256CbcDecryptor = impl::AesCbcCryptor<CbcDecryptor, AesDecryptor256>;
|
||||
|
||||
size_t EncryptAes128Cbc(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
size_t EncryptAes192Cbc(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
size_t EncryptAes256Cbc(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
|
||||
size_t DecryptAes128Cbc(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
size_t DecryptAes192Cbc(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
size_t DecryptAes256Cbc(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
#include <vapours/crypto/crypto_ccm_encryptor.hpp>
|
||||
#include <vapours/crypto/crypto_ccm_decryptor.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<template<typename> typename _CcmImpl, typename _AesImpl>
|
||||
class AesCcmCryptor {
|
||||
NON_COPYABLE(AesCcmCryptor);
|
||||
NON_MOVEABLE(AesCcmCryptor);
|
||||
private:
|
||||
using AesImpl = _AesImpl;
|
||||
using CcmImpl = _CcmImpl<AesImpl>;
|
||||
public:
|
||||
static constexpr size_t KeySize = CcmImpl::KeySize;
|
||||
static constexpr size_t BlockSize = CcmImpl::BlockSize;
|
||||
static constexpr size_t MaxMacSize = CcmImpl::MaxMacSize;
|
||||
static constexpr size_t MaxNonceSize = CcmImpl::MaxNonceSize;
|
||||
private:
|
||||
AesImpl m_aes_impl;
|
||||
CcmImpl m_ccm_impl;
|
||||
public:
|
||||
AesCcmCryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const void *key, size_t key_size, const void *nonce, size_t nonce_size, s64 aad_size, s64 data_size, size_t mac_size) {
|
||||
AMS_ASSERT(key_size == KeySize);
|
||||
AMS_ASSERT(nonce_size <= MaxNonceSize);
|
||||
AMS_ASSERT(mac_size <= MaxMacSize);
|
||||
|
||||
m_aes_impl.Initialize(key, key_size);
|
||||
m_ccm_impl.Initialize(std::addressof(m_aes_impl), nonce, nonce_size, aad_size, data_size, mac_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_ccm_impl.Update(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
void UpdateAad(const void *aad, size_t aad_size) {
|
||||
return m_ccm_impl.UpdateAad(aad, aad_size);
|
||||
}
|
||||
|
||||
void GetMac(void *dst, size_t dst_size) {
|
||||
return m_ccm_impl.GetMac(dst, dst_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using Aes128CcmEncryptor = impl::AesCcmCryptor<CcmEncryptor, AesEncryptor128>;
|
||||
using Aes128CcmDecryptor = impl::AesCcmCryptor<CcmDecryptor, AesEncryptor128>;
|
||||
|
||||
inline size_t EncryptAes128Ccm(void *dst, size_t dst_size, void *mac, size_t mac_buf_size, const void *key, size_t key_size, const void *nonce, size_t nonce_size, const void *src, size_t src_size, const void *aad, size_t aad_size, size_t mac_size) {
|
||||
/* Create encryptor. */
|
||||
Aes128CcmEncryptor ccm;
|
||||
ccm.Initialize(key, key_size, nonce, nonce_size, aad_size, src_size, mac_size);
|
||||
|
||||
/* Process aad. */
|
||||
if (aad_size > 0) {
|
||||
ccm.UpdateAad(aad, aad_size);
|
||||
}
|
||||
|
||||
/* Process data. */
|
||||
size_t processed = 0;
|
||||
if (src_size > 0) {
|
||||
processed = ccm.Update(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
/* Get mac. */
|
||||
ccm.GetMac(mac, mac_buf_size);
|
||||
return processed;
|
||||
}
|
||||
|
||||
inline size_t DecryptAes128Ccm(void *dst, size_t dst_size, void *mac, size_t mac_buf_size, const void *key, size_t key_size, const void *nonce, size_t nonce_size, const void *src, size_t src_size, const void *aad, size_t aad_size, size_t mac_size) {
|
||||
/* Create decryptor. */
|
||||
Aes128CcmDecryptor ccm;
|
||||
ccm.Initialize(key, key_size, nonce, nonce_size, aad_size, src_size, mac_size);
|
||||
|
||||
/* Process aad. */
|
||||
if (aad_size > 0) {
|
||||
ccm.UpdateAad(aad, aad_size);
|
||||
}
|
||||
|
||||
/* Process data. */
|
||||
size_t processed = 0;
|
||||
if (src_size > 0) {
|
||||
processed = ccm.Update(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
/* Get mac. */
|
||||
ccm.GetMac(mac, mac_buf_size);
|
||||
return processed;
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
#include <vapours/crypto/crypto_ctr_encryptor.hpp>
|
||||
#include <vapours/crypto/crypto_ctr_decryptor.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<template<typename> typename _CtrImpl, typename _AesImpl>
|
||||
class AesCtrCryptor {
|
||||
NON_COPYABLE(AesCtrCryptor);
|
||||
NON_MOVEABLE(AesCtrCryptor);
|
||||
private:
|
||||
using AesImpl = _AesImpl;
|
||||
using CtrImpl = _CtrImpl<AesImpl>;
|
||||
public:
|
||||
static constexpr size_t KeySize = AesImpl::KeySize;
|
||||
static constexpr size_t BlockSize = CtrImpl::BlockSize;
|
||||
static constexpr size_t IvSize = CtrImpl::BlockSize;
|
||||
private:
|
||||
AesImpl m_aes_impl;
|
||||
CtrImpl m_ctr_impl;
|
||||
public:
|
||||
AesCtrCryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const void *key, size_t key_size, const void *iv, size_t iv_size) {
|
||||
this->Initialize(key, key_size, iv, iv_size, 0);
|
||||
}
|
||||
|
||||
void Initialize(const void *key, size_t key_size, const void *iv, size_t iv_size, s64 offset) {
|
||||
AMS_ASSERT(key_size == KeySize);
|
||||
AMS_ASSERT(iv_size == IvSize);
|
||||
AMS_ASSERT(offset >= 0);
|
||||
|
||||
m_aes_impl.Initialize(key, key_size);
|
||||
m_ctr_impl.Initialize(std::addressof(m_aes_impl), iv, iv_size, offset);
|
||||
}
|
||||
|
||||
void SwitchMessage(const void *iv, size_t iv_size) {
|
||||
return m_ctr_impl.SwitchMessage(iv, iv_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_ctr_impl.Update(dst, dst_size, src, src_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using Aes128CtrEncryptor = impl::AesCtrCryptor<CtrEncryptor, AesEncryptor128>;
|
||||
using Aes192CtrEncryptor = impl::AesCtrCryptor<CtrEncryptor, AesEncryptor192>;
|
||||
using Aes256CtrEncryptor = impl::AesCtrCryptor<CtrEncryptor, AesEncryptor256>;
|
||||
|
||||
using Aes128CtrDecryptor = impl::AesCtrCryptor<CtrDecryptor, AesEncryptor128>;
|
||||
using Aes192CtrDecryptor = impl::AesCtrCryptor<CtrDecryptor, AesEncryptor192>;
|
||||
using Aes256CtrDecryptor = impl::AesCtrCryptor<CtrDecryptor, AesEncryptor256>;
|
||||
|
||||
size_t EncryptAes128Ctr(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
size_t EncryptAes192Ctr(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
size_t EncryptAes256Ctr(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
|
||||
size_t DecryptAes128Ctr(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
size_t DecryptAes192Ctr(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
size_t DecryptAes256Ctr(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size);
|
||||
|
||||
size_t EncryptAes128CtrPartial(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, s64 offset, const void *src, size_t src_size);
|
||||
size_t EncryptAes192CtrPartial(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, s64 offset, const void *src, size_t src_size);
|
||||
size_t EncryptAes256CtrPartial(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, s64 offset, const void *src, size_t src_size);
|
||||
|
||||
size_t DecryptAes128CtrPartial(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, s64 offset, const void *src, size_t src_size);
|
||||
size_t DecryptAes192CtrPartial(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, s64 offset, const void *src, size_t src_size);
|
||||
size_t DecryptAes256CtrPartial(void *dst, size_t dst_size, const void *key, size_t key_size, const void *iv, size_t iv_size, s64 offset, const void *src, size_t src_size);
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_aes_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
template<size_t _KeySize>
|
||||
class AesDecryptor {
|
||||
NON_COPYABLE(AesDecryptor);
|
||||
NON_MOVEABLE(AesDecryptor);
|
||||
private:
|
||||
using Impl = impl::AesImpl<_KeySize>;
|
||||
public:
|
||||
static constexpr size_t KeySize = Impl::KeySize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
static constexpr size_t RoundKeySize = Impl::RoundKeySize;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
AesDecryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const void *key, size_t key_size) {
|
||||
m_impl.Initialize(key, key_size, false);
|
||||
}
|
||||
|
||||
void DecryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const {
|
||||
return m_impl.DecryptBlock(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
const u8 *GetRoundKey() const {
|
||||
return m_impl.GetRoundKey();
|
||||
}
|
||||
};
|
||||
|
||||
using AesDecryptor128 = AesDecryptor<16>;
|
||||
using AesDecryptor192 = AesDecryptor<24>;
|
||||
using AesDecryptor256 = AesDecryptor<32>;
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_aes_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
template<size_t _KeySize>
|
||||
class AesEncryptor {
|
||||
NON_COPYABLE(AesEncryptor);
|
||||
NON_MOVEABLE(AesEncryptor);
|
||||
private:
|
||||
using Impl = impl::AesImpl<_KeySize>;
|
||||
public:
|
||||
static constexpr size_t KeySize = Impl::KeySize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
static constexpr size_t RoundKeySize = Impl::RoundKeySize;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
AesEncryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const void *key, size_t key_size) {
|
||||
m_impl.Initialize(key, key_size, true);
|
||||
}
|
||||
|
||||
void EncryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const {
|
||||
return m_impl.EncryptBlock(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
const u8 *GetRoundKey() const {
|
||||
return m_impl.GetRoundKey();
|
||||
}
|
||||
};
|
||||
|
||||
using AesEncryptor128 = AesEncryptor<16>;
|
||||
using AesEncryptor192 = AesEncryptor<24>;
|
||||
using AesEncryptor256 = AesEncryptor<32>;
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
#include <vapours/crypto/crypto_gcm_encryptor.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<typename _AesImpl>
|
||||
class AesGcmEncryptor {
|
||||
NON_COPYABLE(AesGcmEncryptor);
|
||||
NON_MOVEABLE(AesGcmEncryptor);
|
||||
private:
|
||||
using AesImpl = _AesImpl;
|
||||
using GcmImpl = GcmEncryptor<AesImpl>;
|
||||
public:
|
||||
static constexpr size_t KeySize = AesImpl::KeySize;
|
||||
static constexpr size_t BlockSize = AesImpl::BlockSize;
|
||||
static constexpr size_t MacSize = AesImpl::BlockSize;
|
||||
private:
|
||||
AesImpl m_aes_impl;
|
||||
GcmImpl m_gcm_impl;
|
||||
public:
|
||||
AesGcmEncryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const void *key, size_t key_size, const void *iv, size_t iv_size) {
|
||||
m_aes_impl.Initialize(key, key_size);
|
||||
m_gcm_impl.Initialize(std::addressof(m_aes_impl), iv, iv_size);
|
||||
}
|
||||
|
||||
void Reset(const void *iv, size_t iv_size) {
|
||||
m_gcm_impl.Reset(iv, iv_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_gcm_impl.Update(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
void UpdateAad(const void *aad, size_t aad_size) {
|
||||
return m_gcm_impl.UpdateAad(aad, aad_size);
|
||||
}
|
||||
|
||||
void GetMac(void *dst, size_t dst_size) {
|
||||
return m_gcm_impl.GetMac(dst, dst_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using Aes128GcmEncryptor = impl::AesGcmEncryptor<AesEncryptor128>;
|
||||
/* TODO: Validate AAD/GMAC is same for non-128 bit key using Aes192GcmEncryptor = impl::AesGcmEncryptor<AesEncryptor192>; */
|
||||
/* TODO: Validate AAD/GMAC is same for non-128 bit key using Aes256GcmEncryptor = impl::AesGcmEncryptor<AesEncryptor256>; */
|
||||
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
#include <vapours/crypto/crypto_xts_encryptor.hpp>
|
||||
#include <vapours/crypto/crypto_xts_decryptor.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<template<typename> typename _XtsImpl, typename _AesImpl1, typename _AesImpl2>
|
||||
class AesXtsCryptor {
|
||||
NON_COPYABLE(AesXtsCryptor);
|
||||
NON_MOVEABLE(AesXtsCryptor);
|
||||
private:
|
||||
using AesImpl1 = _AesImpl1;
|
||||
using AesImpl2 = _AesImpl2;
|
||||
using XtsImpl = _XtsImpl<AesImpl1>;
|
||||
public:
|
||||
static constexpr size_t KeySize = AesImpl1::KeySize;
|
||||
static constexpr size_t BlockSize = AesImpl1::BlockSize;
|
||||
static constexpr size_t IvSize = AesImpl1::BlockSize;
|
||||
|
||||
static_assert(AesImpl1::KeySize == AesImpl2::KeySize);
|
||||
static_assert(AesImpl1::BlockSize == AesImpl2::BlockSize);
|
||||
private:
|
||||
AesImpl1 m_aes_impl_1;
|
||||
AesImpl2 m_aes_impl_2;
|
||||
XtsImpl m_xts_impl;
|
||||
public:
|
||||
AesXtsCryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const void *key1, const void *key2, size_t key_size, const void *iv, size_t iv_size) {
|
||||
AMS_ASSERT(key_size == KeySize);
|
||||
AMS_ASSERT(iv_size == IvSize);
|
||||
|
||||
m_aes_impl_1.Initialize(key1, key_size);
|
||||
m_aes_impl_2.Initialize(key2, key_size);
|
||||
m_xts_impl.Initialize(std::addressof(m_aes_impl_1), std::addressof(m_aes_impl_2), iv, iv_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_xts_impl.Update(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
size_t Finalize(void *dst, size_t dst_size) {
|
||||
return m_xts_impl.Finalize(dst, dst_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using Aes128XtsEncryptor = impl::AesXtsCryptor<XtsEncryptor, AesEncryptor128, AesEncryptor128>;
|
||||
using Aes192XtsEncryptor = impl::AesXtsCryptor<XtsEncryptor, AesEncryptor192, AesEncryptor192>;
|
||||
using Aes256XtsEncryptor = impl::AesXtsCryptor<XtsEncryptor, AesEncryptor256, AesEncryptor256>;
|
||||
|
||||
using Aes128XtsDecryptor = impl::AesXtsCryptor<XtsDecryptor, AesDecryptor128, AesEncryptor128>;
|
||||
using Aes192XtsDecryptor = impl::AesXtsCryptor<XtsDecryptor, AesDecryptor192, AesEncryptor192>;
|
||||
using Aes256XtsDecryptor = impl::AesXtsCryptor<XtsDecryptor, AesDecryptor256, AesEncryptor256>;
|
||||
|
||||
inline size_t EncryptAes128Xts(void *dst, size_t dst_size, const void *key1, const void *key2, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size) {
|
||||
u8 *dst_u8 = static_cast<u8 *>(dst);
|
||||
const u8 *src_u8 = static_cast<const u8 *>(src);
|
||||
|
||||
Aes128XtsEncryptor xts;
|
||||
xts.Initialize(key1, key2, key_size, iv, iv_size);
|
||||
|
||||
size_t processed = xts.Update(dst_u8, dst_size, src_u8, src_size);
|
||||
dst_u8 += processed;
|
||||
dst_size -= processed;
|
||||
|
||||
processed += xts.Finalize(dst_u8, dst_size);
|
||||
return processed;
|
||||
}
|
||||
|
||||
inline size_t EncryptAes192Xts(void *dst, size_t dst_size, const void *key1, const void *key2, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size) {
|
||||
u8 *dst_u8 = static_cast<u8 *>(dst);
|
||||
const u8 *src_u8 = static_cast<const u8 *>(src);
|
||||
|
||||
Aes192XtsEncryptor xts;
|
||||
xts.Initialize(key1, key2, key_size, iv, iv_size);
|
||||
|
||||
size_t processed = xts.Update(dst_u8, dst_size, src_u8, src_size);
|
||||
dst_u8 += processed;
|
||||
dst_size -= processed;
|
||||
|
||||
processed += xts.Finalize(dst_u8, dst_size);
|
||||
return processed;
|
||||
}
|
||||
|
||||
inline size_t EncryptAes256Xts(void *dst, size_t dst_size, const void *key1, const void *key2, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size) {
|
||||
u8 *dst_u8 = static_cast<u8 *>(dst);
|
||||
const u8 *src_u8 = static_cast<const u8 *>(src);
|
||||
|
||||
Aes256XtsEncryptor xts;
|
||||
xts.Initialize(key1, key2, key_size, iv, iv_size);
|
||||
|
||||
size_t processed = xts.Update(dst_u8, dst_size, src_u8, src_size);
|
||||
dst_u8 += processed;
|
||||
dst_size -= processed;
|
||||
|
||||
processed += xts.Finalize(dst_u8, dst_size);
|
||||
return processed;
|
||||
}
|
||||
|
||||
inline size_t DecryptAes128Xts(void *dst, size_t dst_size, const void *key1, const void *key2, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size) {
|
||||
u8 *dst_u8 = static_cast<u8 *>(dst);
|
||||
const u8 *src_u8 = static_cast<const u8 *>(src);
|
||||
|
||||
Aes128XtsDecryptor xts;
|
||||
xts.Initialize(key1, key2, key_size, iv, iv_size);
|
||||
|
||||
size_t processed = xts.Update(dst_u8, dst_size, src_u8, src_size);
|
||||
dst_u8 += processed;
|
||||
dst_size -= processed;
|
||||
|
||||
processed += xts.Finalize(dst_u8, dst_size);
|
||||
return processed;
|
||||
}
|
||||
|
||||
inline size_t DecryptAes192Xts(void *dst, size_t dst_size, const void *key1, const void *key2, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size) {
|
||||
u8 *dst_u8 = static_cast<u8 *>(dst);
|
||||
const u8 *src_u8 = static_cast<const u8 *>(src);
|
||||
|
||||
Aes192XtsDecryptor xts;
|
||||
xts.Initialize(key1, key2, key_size, iv, iv_size);
|
||||
|
||||
size_t processed = xts.Update(dst_u8, dst_size, src_u8, src_size);
|
||||
dst_u8 += processed;
|
||||
dst_size -= processed;
|
||||
|
||||
processed += xts.Finalize(dst_u8, dst_size);
|
||||
return processed;
|
||||
}
|
||||
|
||||
inline size_t DecryptAes256Xts(void *dst, size_t dst_size, const void *key1, const void *key2, size_t key_size, const void *iv, size_t iv_size, const void *src, size_t src_size) {
|
||||
u8 *dst_u8 = static_cast<u8 *>(dst);
|
||||
const u8 *src_u8 = static_cast<const u8 *>(src);
|
||||
|
||||
Aes256XtsDecryptor xts;
|
||||
xts.Initialize(key1, key2, key_size, iv, iv_size);
|
||||
|
||||
size_t processed = xts.Update(dst_u8, dst_size, src_u8, src_size);
|
||||
dst_u8 += processed;
|
||||
dst_size -= processed;
|
||||
|
||||
processed += xts.Finalize(dst_u8, dst_size);
|
||||
return processed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_cbc_mode_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
/* TODO: C++20 BlockCipher concept */
|
||||
|
||||
template<typename BlockCipher>
|
||||
class CbcDecryptor {
|
||||
NON_COPYABLE(CbcDecryptor);
|
||||
NON_MOVEABLE(CbcDecryptor);
|
||||
private:
|
||||
using Impl = impl::CbcModeImpl<BlockCipher>;
|
||||
public:
|
||||
static constexpr size_t KeySize = Impl::KeySize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
static constexpr size_t IvSize = Impl::IvSize;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
CbcDecryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const BlockCipher *cipher, const void *iv, size_t iv_size) {
|
||||
m_impl.Initialize(cipher, iv, iv_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_impl.UpdateDecryption(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
size_t GetBufferedDataSize() const {
|
||||
return m_impl.GetBufferedDataSize();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_cbc_mode_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
/* TODO: C++20 BlockCipher concept */
|
||||
|
||||
template<typename BlockCipher>
|
||||
class CbcEncryptor {
|
||||
NON_COPYABLE(CbcEncryptor);
|
||||
NON_MOVEABLE(CbcEncryptor);
|
||||
private:
|
||||
using Impl = impl::CbcModeImpl<BlockCipher>;
|
||||
public:
|
||||
static constexpr size_t KeySize = Impl::KeySize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
static constexpr size_t IvSize = Impl::IvSize;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
CbcEncryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const BlockCipher *cipher, const void *iv, size_t iv_size) {
|
||||
m_impl.Initialize(cipher, iv, iv_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_impl.UpdateEncryption(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
size_t GetBufferedDataSize() const {
|
||||
return m_impl.GetBufferedDataSize();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_ccm_mode_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
template<typename BlockCipher>
|
||||
class CcmDecryptor {
|
||||
NON_COPYABLE(CcmDecryptor);
|
||||
NON_MOVEABLE(CcmDecryptor);
|
||||
private:
|
||||
using Impl = impl::CcmModeImpl<BlockCipher>;
|
||||
public:
|
||||
static constexpr size_t KeySize = Impl::KeySize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
static constexpr size_t MaxMacSize = BlockSize;
|
||||
static constexpr size_t MaxNonceSize = 13;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
CcmDecryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const BlockCipher *cipher, const void *nonce, size_t nonce_size, s64 aad_size, s64 data_size, size_t mac_size) {
|
||||
m_impl.Initialize(cipher, nonce, nonce_size, aad_size, data_size, mac_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_impl.UpdateDecryption(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
void UpdateAad(const void *aad, size_t aad_size) {
|
||||
return m_impl.UpdateAad(aad, aad_size);
|
||||
}
|
||||
|
||||
void GetMac(void *dst, size_t dst_size) {
|
||||
return m_impl.GetMac(dst, dst_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_ccm_mode_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
template<typename BlockCipher>
|
||||
class CcmEncryptor {
|
||||
NON_COPYABLE(CcmEncryptor);
|
||||
NON_MOVEABLE(CcmEncryptor);
|
||||
private:
|
||||
using Impl = impl::CcmModeImpl<BlockCipher>;
|
||||
public:
|
||||
static constexpr size_t KeySize = Impl::KeySize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
static constexpr size_t MaxMacSize = BlockSize;
|
||||
static constexpr size_t MaxNonceSize = 13;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
CcmEncryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const BlockCipher *cipher, const void *nonce, size_t nonce_size, s64 aad_size, s64 data_size, size_t mac_size) {
|
||||
m_impl.Initialize(cipher, nonce, nonce_size, aad_size, data_size, mac_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_impl.UpdateEncryption(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
void UpdateAad(const void *aad, size_t aad_size) {
|
||||
return m_impl.UpdateAad(aad, aad_size);
|
||||
}
|
||||
|
||||
void GetMac(void *dst, size_t dst_size) {
|
||||
return m_impl.GetMac(dst, dst_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_cmac_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
template<typename BlockCipher>
|
||||
class CmacGenerator {
|
||||
NON_COPYABLE(CmacGenerator);
|
||||
NON_MOVEABLE(CmacGenerator);
|
||||
private:
|
||||
using Impl = impl::CmacImpl<BlockCipher>;
|
||||
public:
|
||||
static constexpr size_t MacSize = BlockCipher::BlockSize;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
CmacGenerator() { /* ... */ }
|
||||
|
||||
void Initialize(const BlockCipher *cipher) {
|
||||
return m_impl.Initialize(cipher);
|
||||
}
|
||||
|
||||
void Update(const void *data, size_t size) {
|
||||
return m_impl.Update(data, size);
|
||||
}
|
||||
|
||||
void GetMac(void *dst, size_t dst_size) {
|
||||
return m_impl.GetMac(dst, dst_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
void GenerateCryptographicallyRandomBytes(void *dst, size_t dst_size);
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_ctr_mode_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
/* TODO: C++20 BlockCipher concept */
|
||||
|
||||
template<typename BlockCipher>
|
||||
class CtrDecryptor {
|
||||
NON_COPYABLE(CtrDecryptor);
|
||||
NON_MOVEABLE(CtrDecryptor);
|
||||
private:
|
||||
using Impl = impl::CtrModeImpl<BlockCipher>;
|
||||
public:
|
||||
static constexpr size_t KeySize = Impl::KeySize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
static constexpr size_t IvSize = Impl::IvSize;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
CtrDecryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const BlockCipher *cipher, const void *iv, size_t iv_size) {
|
||||
m_impl.Initialize(cipher, iv, iv_size);
|
||||
}
|
||||
|
||||
void Initialize(const BlockCipher *cipher, const void *iv, size_t iv_size, s64 offset) {
|
||||
m_impl.Initialize(cipher, iv, iv_size, offset);
|
||||
}
|
||||
|
||||
void SwitchMessage(const void *iv, size_t iv_size) {
|
||||
m_impl.SwitchMessage(iv, iv_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_impl.Update(dst, dst_size, src, src_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_ctr_mode_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
/* TODO: C++20 BlockCipher concept */
|
||||
|
||||
template<typename BlockCipher>
|
||||
class CtrEncryptor {
|
||||
NON_COPYABLE(CtrEncryptor);
|
||||
NON_MOVEABLE(CtrEncryptor);
|
||||
private:
|
||||
using Impl = impl::CtrModeImpl<BlockCipher>;
|
||||
public:
|
||||
static constexpr size_t KeySize = Impl::KeySize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
static constexpr size_t IvSize = Impl::IvSize;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
CtrEncryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const BlockCipher *cipher, const void *iv, size_t iv_size) {
|
||||
m_impl.Initialize(cipher, iv, iv_size);
|
||||
}
|
||||
|
||||
void Initialize(const BlockCipher *cipher, const void *iv, size_t iv_size, s64 offset) {
|
||||
m_impl.Initialize(cipher, iv, iv_size, offset);
|
||||
}
|
||||
|
||||
void SwitchMessage(const void *iv, size_t iv_size) {
|
||||
m_impl.SwitchMessage(iv, iv_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_impl.Update(dst, dst_size, src, src_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_gcm_mode_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
/* TODO: C++20 BlockCipher concept */
|
||||
|
||||
template<typename BlockCipher>
|
||||
class GcmEncryptor {
|
||||
NON_COPYABLE(GcmEncryptor);
|
||||
NON_MOVEABLE(GcmEncryptor);
|
||||
private:
|
||||
using Impl = impl::GcmModeImpl<BlockCipher>;
|
||||
public:
|
||||
static constexpr size_t KeySize = Impl::KeySize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
static constexpr size_t MacSize = Impl::MacSize;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
GcmEncryptor() { /* ... */ }
|
||||
|
||||
void Initialize(const BlockCipher *cipher, const void *iv, size_t iv_size) {
|
||||
m_impl.Initialize(cipher);
|
||||
m_impl.Reset(iv, iv_size);
|
||||
}
|
||||
|
||||
void Reset(const void *iv, size_t iv_size) {
|
||||
m_impl.Reset(iv, iv_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_impl.Update(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
void UpdateAad(const void *aad, size_t aad_size) {
|
||||
return m_impl.UpdateAad(aad, aad_size);
|
||||
}
|
||||
|
||||
void GetMac(void *dst, size_t dst_size) {
|
||||
return m_impl.GetMac(dst, dst_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_hmac_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
template<typename Hash> /* requires HashFunction<Hash> */
|
||||
class HmacGenerator {
|
||||
NON_COPYABLE(HmacGenerator);
|
||||
NON_MOVEABLE(HmacGenerator);
|
||||
private:
|
||||
using Impl = impl::HmacImpl<Hash>;
|
||||
public:
|
||||
static constexpr size_t HashSize = Impl::HashSize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
HmacGenerator() { /* ... */ }
|
||||
|
||||
void Initialize(const void *key, size_t key_size) {
|
||||
return m_impl.Initialize(key, key_size);
|
||||
}
|
||||
|
||||
void Update(const void *data, size_t size) {
|
||||
return m_impl.Update(data, size);
|
||||
}
|
||||
|
||||
void GetMac(void *dst, size_t dst_size) {
|
||||
return m_impl.GetMac(dst, dst_size);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/crypto/crypto_sha1_generator.hpp>
|
||||
#include <vapours/crypto/crypto_hmac_generator.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
using HmacSha1Generator = HmacGenerator<Sha1Generator>;
|
||||
|
||||
void GenerateHmacSha1(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size);
|
||||
|
||||
ALWAYS_INLINE void GenerateHmacSha1Mac(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size) {
|
||||
return GenerateHmacSha1(dst, dst_size, data, data_size, key, key_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/crypto/crypto_sha256_generator.hpp>
|
||||
#include <vapours/crypto/crypto_hmac_generator.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
using HmacSha256Generator = HmacGenerator<Sha256Generator>;
|
||||
|
||||
void GenerateHmacSha256(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size);
|
||||
|
||||
ALWAYS_INLINE void GenerateHmacSha256Mac(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size) {
|
||||
return GenerateHmacSha256(dst, dst_size, data, data_size, key, key_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_md5_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
class Md5Generator {
|
||||
NON_COPYABLE(Md5Generator);
|
||||
NON_MOVEABLE(Md5Generator);
|
||||
private:
|
||||
using Impl = impl::Md5Impl;
|
||||
public:
|
||||
static constexpr size_t HashSize = Impl::HashSize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
|
||||
static constexpr inline const u8 Asn1Identifier[] = {
|
||||
0x30, 0x20, /* Sequence, size 0x20 */
|
||||
0x30, 0x0C, /* Sequence, size 0x0C */
|
||||
0x06, 0x08, /* Object Identifier */
|
||||
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* MD5 */
|
||||
0x05, 0x00, /* Null */
|
||||
0x04, 0x10, /* Octet string, size 0x10 */
|
||||
};
|
||||
static constexpr size_t Asn1IdentifierSize = util::size(Asn1Identifier);
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
Md5Generator() { /* ... */ }
|
||||
|
||||
void Initialize() {
|
||||
m_impl.Initialize();
|
||||
}
|
||||
|
||||
void Update(const void *data, size_t size) {
|
||||
m_impl.Update(data, size);
|
||||
}
|
||||
|
||||
void GetHash(void *dst, size_t size) {
|
||||
m_impl.GetHash(dst, size);
|
||||
}
|
||||
};
|
||||
|
||||
void GenerateMd5(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
|
||||
ALWAYS_INLINE void GenerateMd5Hash(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return GenerateMd5(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
void ClearMemory(void *mem, size_t size);
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
bool IsSameBytes(const void *lhs, const void *rhs, size_t size);
|
||||
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_bignum.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
template<size_t ModulusSize, size_t ExponentSize>
|
||||
class RsaCalculator {
|
||||
NON_COPYABLE(RsaCalculator);
|
||||
NON_MOVEABLE(RsaCalculator);
|
||||
public:
|
||||
static constexpr inline size_t RequiredWorkBufferSize = 0x10 * ModulusSize;
|
||||
private:
|
||||
impl::StaticBigNum<ModulusSize * BITSIZEOF(u8)> m_modulus;
|
||||
impl::StaticBigNum<ExponentSize * BITSIZEOF(u8)> m_exponent;
|
||||
public:
|
||||
RsaCalculator() { /* ... */ }
|
||||
~RsaCalculator() { m_exponent.ClearToZero(); }
|
||||
|
||||
bool Initialize(const void *mod, size_t mod_size, const void *exp, size_t exp_size) {
|
||||
if (!m_modulus.Import(mod, mod_size) || m_modulus.IsZero()) {
|
||||
return false;
|
||||
}
|
||||
if (!m_exponent.Import(exp, exp_size) || m_exponent.IsZero()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExpMod(void *dst, const void *src, size_t size, void *work_buf, size_t work_buf_size) {
|
||||
AMS_ASSERT(work_buf_size >= RequiredWorkBufferSize);
|
||||
|
||||
return m_modulus.ExpMod(dst, src, size, m_exponent, static_cast<u32 *>(work_buf), work_buf_size);
|
||||
}
|
||||
|
||||
bool ExpMod(void *dst, const void *src, size_t size) {
|
||||
u32 work_buf[RequiredWorkBufferSize / sizeof(u32)];
|
||||
return this->ExpMod(dst, src, size, work_buf, sizeof(work_buf));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_calculator.hpp>
|
||||
#include <vapours/crypto/impl/crypto_rsa_oaep_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
template<size_t ModulusSize, typename Hash> requires impl::HashFunction<Hash>
|
||||
class RsaOaepDecryptor {
|
||||
NON_COPYABLE(RsaOaepDecryptor);
|
||||
NON_MOVEABLE(RsaOaepDecryptor);
|
||||
public:
|
||||
static constexpr size_t HashSize = Hash::HashSize;
|
||||
static constexpr size_t BlockSize = ModulusSize;
|
||||
static constexpr size_t MaximumExponentSize = ModulusSize;
|
||||
static constexpr size_t RequiredWorkBufferSize = RsaCalculator<ModulusSize, MaximumExponentSize>::RequiredWorkBufferSize;
|
||||
private:
|
||||
enum class State {
|
||||
None,
|
||||
Initialized,
|
||||
Done,
|
||||
};
|
||||
private:
|
||||
RsaCalculator<ModulusSize, MaximumExponentSize> m_calculator;
|
||||
Hash m_hash;
|
||||
bool m_set_label_digest;
|
||||
u8 m_label_digest[HashSize];
|
||||
State m_state;
|
||||
public:
|
||||
RsaOaepDecryptor() : m_set_label_digest(false), m_state(State::None) { std::memset(m_label_digest, 0, sizeof(m_label_digest)); }
|
||||
|
||||
~RsaOaepDecryptor() {
|
||||
ClearMemory(m_label_digest, sizeof(m_label_digest));
|
||||
}
|
||||
|
||||
bool Initialize(const void *mod, size_t mod_size, const void *exp, size_t exp_size) {
|
||||
m_hash.Initialize();
|
||||
m_set_label_digest = false;
|
||||
if (m_calculator.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
m_state = State::Initialized;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateLabel(const void *data, size_t size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
|
||||
m_hash.Update(data, size);
|
||||
}
|
||||
|
||||
void SetLabelDigest(const void *digest, size_t digest_size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_ABORT_UNLESS(digest_size == sizeof(m_label_digest));
|
||||
|
||||
std::memcpy(m_label_digest, digest, digest_size);
|
||||
m_set_label_digest = true;
|
||||
}
|
||||
|
||||
size_t Decrypt(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
|
||||
impl::RsaOaepImpl<Hash> impl;
|
||||
u8 message[BlockSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(message, sizeof(message)); };
|
||||
|
||||
if (!m_calculator.ExpMod(message, src, src_size)) {
|
||||
std::memset(dst, 0, dst_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_set_label_digest) {
|
||||
m_hash.GetHash(m_label_digest, sizeof(m_label_digest));
|
||||
}
|
||||
|
||||
ON_SCOPE_EXIT { m_state = State::Done; };
|
||||
|
||||
return impl.Decode(dst, dst_size, m_label_digest, sizeof(m_label_digest), message, sizeof(message));
|
||||
}
|
||||
|
||||
size_t Decrypt(void *dst, size_t dst_size, const void *src, size_t src_size, void *work_buf, size_t work_buf_size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
ON_SCOPE_EXIT { m_state = State::Done; };
|
||||
|
||||
impl::RsaOaepImpl<Hash> impl;
|
||||
u8 message[BlockSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(message, sizeof(message)); };
|
||||
|
||||
if (!m_calculator.ExpMod(message, src, src_size, work_buf, work_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_set_label_digest) {
|
||||
m_hash.GetHash(m_label_digest, sizeof(m_label_digest));
|
||||
m_set_label_digest = true;
|
||||
}
|
||||
|
||||
return impl.Decode(dst, dst_size, m_label_digest, sizeof(m_label_digest), message, sizeof(message));
|
||||
}
|
||||
|
||||
static size_t Decrypt(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *lab, size_t lab_size) {
|
||||
RsaOaepDecryptor<ModulusSize, Hash> crypt;
|
||||
if (!crypt.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
return 0;
|
||||
}
|
||||
crypt.UpdateLabel(lab, lab_size);
|
||||
return crypt.Decrypt(dst, dst_size, msg, msg_size);
|
||||
}
|
||||
|
||||
static size_t Decrypt(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *lab, size_t lab_size, void *work_buf, size_t work_buf_size) {
|
||||
RsaOaepDecryptor<ModulusSize, Hash> crypt;
|
||||
if (!crypt.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
return 0;
|
||||
}
|
||||
crypt.UpdateLabel(lab, lab_size);
|
||||
return crypt.Decrypt(dst, dst_size, msg, msg_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_calculator.hpp>
|
||||
#include <vapours/crypto/impl/crypto_rsa_oaep_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
template<size_t ModulusSize, typename Hash> requires impl::HashFunction<Hash>
|
||||
class RsaOaepEncryptor {
|
||||
NON_COPYABLE(RsaOaepEncryptor);
|
||||
NON_MOVEABLE(RsaOaepEncryptor);
|
||||
public:
|
||||
static constexpr size_t HashSize = Hash::HashSize;
|
||||
static constexpr size_t BlockSize = ModulusSize;
|
||||
static constexpr size_t MaximumExponentSize = 3;
|
||||
static constexpr size_t RequiredWorkBufferSize = RsaCalculator<ModulusSize, MaximumExponentSize>::RequiredWorkBufferSize;
|
||||
private:
|
||||
enum class State {
|
||||
None,
|
||||
Initialized,
|
||||
Done,
|
||||
};
|
||||
private:
|
||||
RsaCalculator<ModulusSize, MaximumExponentSize> m_calculator;
|
||||
Hash m_hash;
|
||||
bool m_set_label_digest;
|
||||
u8 m_label_digest[HashSize];
|
||||
State m_state;
|
||||
public:
|
||||
RsaOaepEncryptor() : m_set_label_digest(false), m_state(State::None) { std::memset(m_label_digest, 0, sizeof(m_label_digest)); }
|
||||
|
||||
~RsaOaepEncryptor() {
|
||||
ClearMemory(m_label_digest, sizeof(m_label_digest));
|
||||
}
|
||||
|
||||
bool Initialize(const void *mod, size_t mod_size, const void *exp, size_t exp_size) {
|
||||
m_hash.Initialize();
|
||||
m_set_label_digest = false;
|
||||
if (m_calculator.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
m_state = State::Initialized;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateLabel(const void *data, size_t size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
|
||||
m_hash.Update(data, size);
|
||||
}
|
||||
|
||||
void SetLabelDigest(const void *digest, size_t digest_size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_ABORT_UNLESS(digest_size == sizeof(m_label_digest));
|
||||
|
||||
std::memcpy(m_label_digest, digest, digest_size);
|
||||
m_set_label_digest = true;
|
||||
}
|
||||
|
||||
bool Encrypt(void *dst, size_t dst_size, const void *src, size_t src_size, const void *salt, size_t salt_size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
|
||||
impl::RsaOaepImpl<Hash> impl;
|
||||
if (!m_set_label_digest) {
|
||||
m_hash.GetHash(m_label_digest, sizeof(m_label_digest));
|
||||
}
|
||||
|
||||
impl.Encode(dst, dst_size, m_label_digest, sizeof(m_label_digest), src, src_size, salt, salt_size);
|
||||
|
||||
if (!m_calculator.ExpMod(dst, dst, dst_size)) {
|
||||
std::memset(dst, 0, dst_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_state = State::Done;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Encrypt(void *dst, size_t dst_size, const void *src, size_t src_size, const void *salt, size_t salt_size, void *work, size_t work_size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
|
||||
impl::RsaOaepImpl<Hash> impl;
|
||||
if (!m_set_label_digest) {
|
||||
m_hash.GetHash(m_label_digest, sizeof(m_label_digest));
|
||||
}
|
||||
|
||||
impl.Encode(dst, dst_size, m_label_digest, sizeof(m_label_digest), src, src_size, salt, salt_size);
|
||||
|
||||
if (!m_calculator.ExpMod(dst, dst, dst_size, work, work_size)) {
|
||||
std::memset(dst, 0, dst_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_state = State::Done;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Encrypt(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *seed, size_t seed_size, const void *lab, size_t lab_size) {
|
||||
RsaOaepEncryptor<ModulusSize, Hash> oaep;
|
||||
if (!oaep.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
return false;
|
||||
}
|
||||
oaep.UpdateLabel(lab, lab_size);
|
||||
return oaep.Encrypt(dst, dst_size, msg, msg_size, seed, seed_size);
|
||||
}
|
||||
|
||||
static bool Encrypt(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *seed, size_t seed_size, const void *lab, size_t lab_size, void *work, size_t work_size) {
|
||||
RsaOaepEncryptor<ModulusSize, Hash> oaep;
|
||||
if (!oaep.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
return false;
|
||||
}
|
||||
oaep.UpdateLabel(lab, lab_size);
|
||||
return oaep.Encrypt(dst, dst_size, msg, msg_size, seed, seed_size, work, work_size);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_rsa_oaep_impl.hpp>
|
||||
#include <vapours/crypto/crypto_sha256_generator.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
inline size_t DecodeRsa2048OaepSha256(void *dst, size_t dst_size, const void *label_digest, size_t label_digest_size, const void *src, size_t src_size) {
|
||||
constexpr size_t BlockSize = 2048 / BITSIZEOF(u8);
|
||||
AMS_ABORT_UNLESS(src_size == BlockSize);
|
||||
|
||||
impl::RsaOaepImpl<Sha256Generator> oaep;
|
||||
u8 enc[BlockSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(enc, sizeof(enc)); };
|
||||
|
||||
std::memcpy(enc, src, src_size);
|
||||
return oaep.Decode(dst, dst_size, label_digest, label_digest_size, enc, sizeof(enc));
|
||||
}
|
||||
|
||||
inline size_t DecodeRsa4096OaepSha256(void *dst, size_t dst_size, const void *label_digest, size_t label_digest_size, const void *src, size_t src_size) {
|
||||
constexpr size_t BlockSize = 4096 / BITSIZEOF(u8);
|
||||
AMS_ABORT_UNLESS(src_size == BlockSize);
|
||||
|
||||
impl::RsaOaepImpl<Sha256Generator> oaep;
|
||||
u8 enc[BlockSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(enc, sizeof(enc)); };
|
||||
|
||||
std::memcpy(enc, src, src_size);
|
||||
return oaep.Decode(dst, dst_size, label_digest, label_digest_size, enc, sizeof(enc));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_calculator.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_oaep_decryptor.hpp>
|
||||
#include <vapours/crypto/crypto_sha256_generator.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<size_t Bits>
|
||||
using RsaNOaepSha256Decryptor = ::ams::crypto::RsaOaepDecryptor<Bits / BITSIZEOF(u8), ::ams::crypto::Sha256Generator>;
|
||||
|
||||
}
|
||||
|
||||
using Rsa2048OaepSha256Decryptor = ::ams::crypto::impl::RsaNOaepSha256Decryptor<2048>;
|
||||
using Rsa4096OaepSha256Decryptor = ::ams::crypto::impl::RsaNOaepSha256Decryptor<4096>;
|
||||
|
||||
inline size_t DecryptRsa2048OaepSha256(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *lab, size_t lab_size) {
|
||||
return Rsa2048OaepSha256Decryptor::Decrypt(dst, dst_size, mod, mod_size, exp, exp_size, msg, msg_size, lab, lab_size);
|
||||
}
|
||||
|
||||
inline size_t DecryptRsa2048OaepSha256(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *lab, size_t lab_size, void *work_buf, size_t work_buf_size) {
|
||||
return Rsa2048OaepSha256Decryptor::Decrypt(dst, dst_size, mod, mod_size, exp, exp_size, msg, msg_size, lab, lab_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
inline size_t DecryptRsa4096OaepSha256(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *lab, size_t lab_size) {
|
||||
return Rsa4096OaepSha256Decryptor::Decrypt(dst, dst_size, mod, mod_size, exp, exp_size, msg, msg_size, lab, lab_size);
|
||||
}
|
||||
|
||||
inline size_t DecryptRsa4096OaepSha256(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *lab, size_t lab_size, void *work_buf, size_t work_buf_size) {
|
||||
return Rsa4096OaepSha256Decryptor::Decrypt(dst, dst_size, mod, mod_size, exp, exp_size, msg, msg_size, lab, lab_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_calculator.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_oaep_encryptor.hpp>
|
||||
#include <vapours/crypto/crypto_sha256_generator.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<size_t Bits>
|
||||
using RsaNOaepSha256Encryptor = ::ams::crypto::RsaOaepEncryptor<Bits / BITSIZEOF(u8), ::ams::crypto::Sha256Generator>;
|
||||
|
||||
}
|
||||
|
||||
using Rsa2048OaepSha256Encryptor = ::ams::crypto::impl::RsaNOaepSha256Encryptor<2048>;
|
||||
using Rsa4096OaepSha256Encryptor = ::ams::crypto::impl::RsaNOaepSha256Encryptor<4096>;
|
||||
|
||||
inline size_t EncryptRsa2048OaepSha256(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *salt, size_t salt_size, const void *lab, size_t lab_size) {
|
||||
return Rsa2048OaepSha256Encryptor::Encrypt(dst, dst_size, mod, mod_size, exp, exp_size, msg, msg_size, salt, salt_size, lab, lab_size);
|
||||
}
|
||||
|
||||
inline size_t EncryptRsa2048OaepSha256(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *salt, size_t salt_size, const void *lab, size_t lab_size, void *work_buf, size_t work_buf_size) {
|
||||
return Rsa2048OaepSha256Encryptor::Encrypt(dst, dst_size, mod, mod_size, exp, exp_size, msg, msg_size, salt, salt_size, lab, lab_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
inline size_t EncryptRsa4096OaepSha256(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *salt, size_t salt_size, const void *lab, size_t lab_size) {
|
||||
return Rsa4096OaepSha256Encryptor::Encrypt(dst, dst_size, mod, mod_size, exp, exp_size, msg, msg_size, salt, salt_size, lab, lab_size);
|
||||
}
|
||||
|
||||
inline size_t EncryptRsa4096OaepSha256(void *dst, size_t dst_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, const void *salt, size_t salt_size, const void *lab, size_t lab_size, void *work_buf, size_t work_buf_size) {
|
||||
return Rsa4096OaepSha256Encryptor::Encrypt(dst, dst_size, mod, mod_size, exp, exp_size, msg, msg_size, salt, salt_size, lab, lab_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_calculator.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_pkcs1_verifier.hpp>
|
||||
#include <vapours/crypto/crypto_sha256_generator.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<size_t Bits>
|
||||
using RsaNPkcs1Sha256Verifier = ::ams::crypto::RsaPkcs1Verifier<Bits / BITSIZEOF(u8), ::ams::crypto::Sha256Generator>;
|
||||
|
||||
}
|
||||
|
||||
using Rsa2048Pkcs1Sha256Verifier = ::ams::crypto::impl::RsaNPkcs1Sha256Verifier<2048>;
|
||||
using Rsa4096Pkcs1Sha256Verifier = ::ams::crypto::impl::RsaNPkcs1Sha256Verifier<4096>;
|
||||
|
||||
inline bool VerifyRsa2048Pkcs1Sha256(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size) {
|
||||
return Rsa2048Pkcs1Sha256Verifier::Verify(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size);
|
||||
}
|
||||
|
||||
inline bool VerifyRsa2048Pkcs1Sha256(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, void *work_buf, size_t work_buf_size) {
|
||||
return Rsa2048Pkcs1Sha256Verifier::Verify(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
inline bool VerifyRsa4096Pkcs1Sha256(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size) {
|
||||
return Rsa4096Pkcs1Sha256Verifier::Verify(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size);
|
||||
}
|
||||
|
||||
inline bool VerifyRsa4096Pkcs1Sha256(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, void *work_buf, size_t work_buf_size) {
|
||||
return Rsa4096Pkcs1Sha256Verifier::Verify(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_calculator.hpp>
|
||||
#include <vapours/crypto/impl/crypto_rsa_pkcs1_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
template<size_t _ModulusSize, impl::HashFunction Hash>
|
||||
class RsaPkcs1Verifier {
|
||||
NON_COPYABLE(RsaPkcs1Verifier);
|
||||
NON_MOVEABLE(RsaPkcs1Verifier);
|
||||
public:
|
||||
static constexpr size_t HashSize = Hash::HashSize;
|
||||
static constexpr size_t ModulusSize = _ModulusSize;
|
||||
static constexpr size_t SignatureSize = ModulusSize;
|
||||
static constexpr size_t MaximumExponentSize = 3;
|
||||
static constexpr size_t RequiredWorkBufferSize = RsaCalculator<ModulusSize, MaximumExponentSize>::RequiredWorkBufferSize;
|
||||
private:
|
||||
enum class State {
|
||||
None,
|
||||
Initialized,
|
||||
Done,
|
||||
};
|
||||
private:
|
||||
RsaCalculator<ModulusSize, MaximumExponentSize> m_calculator;
|
||||
Hash m_hash;
|
||||
State m_state;
|
||||
public:
|
||||
RsaPkcs1Verifier() : m_state(State::None) { /* ... */ }
|
||||
|
||||
bool Initialize(const void *mod, size_t mod_size, const void *exp, size_t exp_size) {
|
||||
m_hash.Initialize();
|
||||
if (m_calculator.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
m_state = State::Initialized;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Update(const void *data, size_t size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
return m_hash.Update(data, size);
|
||||
}
|
||||
|
||||
bool Verify(const void *signature, size_t size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_ASSERT(size == SignatureSize);
|
||||
AMS_UNUSED(size);
|
||||
ON_SCOPE_EXIT { m_state = State::Done; };
|
||||
|
||||
impl::RsaPkcs1Impl<Hash> impl;
|
||||
u8 message[SignatureSize];
|
||||
|
||||
return m_calculator.ExpMod(message, signature, SignatureSize) && impl.CheckPad(message, sizeof(message), std::addressof(m_hash));
|
||||
}
|
||||
|
||||
bool Verify(const void *signature, size_t size, void *work_buf, size_t work_buf_size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_ASSERT(size == SignatureSize);
|
||||
AMS_UNUSED(size);
|
||||
ON_SCOPE_EXIT { m_state = State::Done; };
|
||||
|
||||
impl::RsaPkcs1Impl<Hash> impl;
|
||||
u8 message[SignatureSize];
|
||||
|
||||
return m_calculator.ExpMod(message, signature, SignatureSize, work_buf, work_buf_size) && impl.CheckPad(message, sizeof(message), std::addressof(m_hash));
|
||||
}
|
||||
|
||||
void GetHash(void *dst, size_t dst_size) {
|
||||
AMS_ASSERT(m_state == State::Done);
|
||||
|
||||
if (m_state == State::Done) {
|
||||
m_hash.GetHash(dst, dst_size);
|
||||
}
|
||||
}
|
||||
|
||||
static bool Verify(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size) {
|
||||
RsaPkcs1Verifier<ModulusSize, Hash> verifier;
|
||||
if (!verifier.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
return false;
|
||||
}
|
||||
verifier.Update(msg, msg_size);
|
||||
return verifier.Verify(sig, sig_size);
|
||||
}
|
||||
|
||||
static bool Verify(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, void *work_buf, size_t work_buf_size) {
|
||||
RsaPkcs1Verifier<ModulusSize, Hash> verifier;
|
||||
if (!verifier.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
return false;
|
||||
}
|
||||
verifier.Update(msg, msg_size);
|
||||
return verifier.Verify(sig, sig_size, work_buf, work_buf_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_calculator.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_pss_verifier.hpp>
|
||||
#include <vapours/crypto/crypto_sha256_generator.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<size_t Bits>
|
||||
using RsaNPssSha256Verifier = ::ams::crypto::RsaPssVerifier<Bits / BITSIZEOF(u8), ::ams::crypto::Sha256Generator>;
|
||||
|
||||
}
|
||||
|
||||
using Rsa2048PssSha256Verifier = ::ams::crypto::impl::RsaNPssSha256Verifier<2048>;
|
||||
using Rsa4096PssSha256Verifier = ::ams::crypto::impl::RsaNPssSha256Verifier<4096>;
|
||||
|
||||
inline bool VerifyRsa2048PssSha256(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size) {
|
||||
return Rsa2048PssSha256Verifier::Verify(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size);
|
||||
}
|
||||
|
||||
inline bool VerifyRsa2048PssSha256(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, void *work_buf, size_t work_buf_size) {
|
||||
return Rsa2048PssSha256Verifier::Verify(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
inline bool VerifyRsa2048PssSha256WithHash(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *hash, size_t hash_size) {
|
||||
return Rsa2048PssSha256Verifier::VerifyWithHash(sig, sig_size, mod, mod_size, exp, exp_size, hash, hash_size);
|
||||
}
|
||||
|
||||
inline bool VerifyRsa2048PssSha256WithHash(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *hash, size_t hash_size, void *work_buf, size_t work_buf_size) {
|
||||
return Rsa2048PssSha256Verifier::VerifyWithHash(sig, sig_size, mod, mod_size, exp, exp_size, hash, hash_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
inline bool VerifyRsa4096PssSha256(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size) {
|
||||
return Rsa4096PssSha256Verifier::Verify(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size);
|
||||
}
|
||||
|
||||
inline bool VerifyRsa4096PssSha256(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, void *work_buf, size_t work_buf_size) {
|
||||
return Rsa4096PssSha256Verifier::Verify(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
inline bool VerifyRsa4096PssSha256WithHash(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *hash, size_t hash_size) {
|
||||
return Rsa4096PssSha256Verifier::VerifyWithHash(sig, sig_size, mod, mod_size, exp, exp_size, hash, hash_size);
|
||||
}
|
||||
|
||||
inline bool VerifyRsa4096PssSha256WithHash(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *hash, size_t hash_size, void *work_buf, size_t work_buf_size) {
|
||||
return Rsa4096PssSha256Verifier::VerifyWithHash(sig, sig_size, mod, mod_size, exp, exp_size, hash, hash_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_rsa_calculator.hpp>
|
||||
#include <vapours/crypto/impl/crypto_rsa_pss_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
template<size_t _ModulusSize, typename Hash> requires impl::HashFunction<Hash>
|
||||
class RsaPssVerifier {
|
||||
NON_COPYABLE(RsaPssVerifier);
|
||||
NON_MOVEABLE(RsaPssVerifier);
|
||||
public:
|
||||
static constexpr size_t HashSize = Hash::HashSize;
|
||||
static constexpr size_t SaltSize = Hash::HashSize;
|
||||
static constexpr size_t ModulusSize = _ModulusSize;
|
||||
static constexpr size_t SignatureSize = ModulusSize;
|
||||
static constexpr size_t MaximumExponentSize = 3;
|
||||
static constexpr size_t RequiredWorkBufferSize = RsaCalculator<ModulusSize, MaximumExponentSize>::RequiredWorkBufferSize;
|
||||
private:
|
||||
enum class State {
|
||||
None,
|
||||
Initialized,
|
||||
Done,
|
||||
};
|
||||
private:
|
||||
RsaCalculator<ModulusSize, MaximumExponentSize> m_calculator;
|
||||
Hash m_hash;
|
||||
State m_state;
|
||||
public:
|
||||
RsaPssVerifier() : m_state(State::None) { /* ... */ }
|
||||
~RsaPssVerifier() { }
|
||||
|
||||
bool Initialize(const void *mod, size_t mod_size, const void *exp, size_t exp_size) {
|
||||
m_hash.Initialize();
|
||||
if (m_calculator.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
m_state = State::Initialized;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Update(const void *data, size_t size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
return m_hash.Update(data, size);
|
||||
}
|
||||
|
||||
bool Verify(const void *signature, size_t size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_ASSERT(size == SignatureSize);
|
||||
AMS_UNUSED(size);
|
||||
ON_SCOPE_EXIT { m_state = State::Done; };
|
||||
|
||||
impl::RsaPssImpl<Hash> impl;
|
||||
u8 message[SignatureSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(message, sizeof(message)); };
|
||||
|
||||
if (!m_calculator.ExpMod(message, signature, SignatureSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
u8 calc_hash[Hash::HashSize];
|
||||
m_hash.GetHash(calc_hash, sizeof(calc_hash));
|
||||
ON_SCOPE_EXIT { ClearMemory(calc_hash, sizeof(calc_hash)); };
|
||||
|
||||
return impl.Verify(message, sizeof(message), calc_hash, sizeof(calc_hash));
|
||||
}
|
||||
|
||||
bool Verify(const void *signature, size_t size, void *work_buf, size_t work_buf_size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_ASSERT(size == SignatureSize);
|
||||
AMS_UNUSED(size);
|
||||
ON_SCOPE_EXIT { m_state = State::Done; };
|
||||
|
||||
impl::RsaPssImpl<Hash> impl;
|
||||
u8 message[SignatureSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(message, sizeof(message)); };
|
||||
|
||||
if (!m_calculator.ExpMod(message, signature, SignatureSize, work_buf, work_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
u8 calc_hash[Hash::HashSize];
|
||||
m_hash.GetHash(calc_hash, sizeof(calc_hash));
|
||||
ON_SCOPE_EXIT { ClearMemory(calc_hash, sizeof(calc_hash)); };
|
||||
|
||||
return impl.Verify(message, sizeof(message), calc_hash, sizeof(calc_hash));
|
||||
}
|
||||
|
||||
bool VerifyWithHash(const void *signature, size_t size, const void *hash, size_t hash_size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_ASSERT(size == SignatureSize);
|
||||
AMS_UNUSED(size);
|
||||
ON_SCOPE_EXIT { m_state = State::Done; };
|
||||
|
||||
impl::RsaPssImpl<Hash> impl;
|
||||
u8 message[SignatureSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(message, sizeof(message)); };
|
||||
|
||||
if (!m_calculator.ExpMod(message, signature, SignatureSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return impl.Verify(message, sizeof(message), static_cast<const u8 *>(hash), hash_size);
|
||||
}
|
||||
|
||||
bool VerifyWithHash(const void *signature, size_t size, const void *hash, size_t hash_size, void *work_buf, size_t work_buf_size) {
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_ASSERT(size == SignatureSize);
|
||||
AMS_UNUSED(size);
|
||||
ON_SCOPE_EXIT { m_state = State::Done; };
|
||||
|
||||
impl::RsaPssImpl<Hash> impl;
|
||||
u8 message[SignatureSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(message, sizeof(message)); };
|
||||
|
||||
if (!m_calculator.ExpMod(message, signature, SignatureSize, work_buf, work_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return impl.Verify(message, sizeof(message), static_cast<const u8 *>(hash), hash_size);
|
||||
}
|
||||
|
||||
static bool Verify(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size) {
|
||||
RsaPssVerifier<ModulusSize, Hash> verifier;
|
||||
if (!verifier.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
return false;
|
||||
}
|
||||
verifier.Update(msg, msg_size);
|
||||
return verifier.Verify(sig, sig_size);
|
||||
}
|
||||
|
||||
static bool Verify(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *msg, size_t msg_size, void *work_buf, size_t work_buf_size) {
|
||||
RsaPssVerifier<ModulusSize, Hash> verifier;
|
||||
if (!verifier.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
return false;
|
||||
}
|
||||
verifier.Update(msg, msg_size);
|
||||
return verifier.Verify(sig, sig_size, work_buf, work_buf_size);
|
||||
}
|
||||
|
||||
static bool VerifyWithHash(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *hash, size_t hash_size) {
|
||||
RsaPssVerifier<ModulusSize, Hash> verifier;
|
||||
if (!verifier.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
return false;
|
||||
}
|
||||
return verifier.VerifyWithHash(sig, sig_size, hash, hash_size);
|
||||
}
|
||||
|
||||
static bool VerifyWithHash(const void *sig, size_t sig_size, const void *mod, size_t mod_size, const void *exp, size_t exp_size, const void *hash, size_t hash_size, void *work_buf, size_t work_buf_size) {
|
||||
RsaPssVerifier<ModulusSize, Hash> verifier;
|
||||
if (!verifier.Initialize(mod, mod_size, exp, exp_size)) {
|
||||
return false;
|
||||
}
|
||||
return verifier.VerifyWithHash(sig, sig_size, hash, hash_size, work_buf, work_buf_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_sha1_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
class Sha1Generator {
|
||||
NON_COPYABLE(Sha1Generator);
|
||||
NON_MOVEABLE(Sha1Generator);
|
||||
private:
|
||||
using Impl = impl::Sha1Impl;
|
||||
public:
|
||||
static constexpr size_t HashSize = Impl::HashSize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
|
||||
static constexpr inline u8 Asn1Identifier[] = {
|
||||
0x30, 0x21, /* Sequence, size 0x21 */
|
||||
0x30, 0x09, /* Sequence, size 0x09 */
|
||||
0x06, 0x05, /* Object Identifier */
|
||||
0x2B, 0x0E, 0x03, 0x02, 0x1A, /* SHA-1 */
|
||||
0x05, 0x00, /* Null */
|
||||
0x04, 0x14, /* Octet string, size 0x14 */
|
||||
};
|
||||
static constexpr size_t Asn1IdentifierSize = util::size(Asn1Identifier);
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
Sha1Generator() { /* ... */ }
|
||||
|
||||
void Initialize() {
|
||||
m_impl.Initialize();
|
||||
}
|
||||
|
||||
void Update(const void *data, size_t size) {
|
||||
m_impl.Update(data, size);
|
||||
}
|
||||
|
||||
void GetHash(void *dst, size_t size) {
|
||||
m_impl.GetHash(dst, size);
|
||||
}
|
||||
};
|
||||
|
||||
void GenerateSha1(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
|
||||
ALWAYS_INLINE void GenerateSha1Hash(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return GenerateSha1(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_sha256_impl.hpp>
|
||||
#include <vapours/crypto/impl/crypto_sha256_impl_constexpr.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
struct Sha256Context {
|
||||
u32 intermediate_hash[impl::Sha256Impl::HashSize / sizeof(u32)];
|
||||
u64 bits_consumed;
|
||||
};
|
||||
|
||||
class Sha256Generator {
|
||||
NON_COPYABLE(Sha256Generator);
|
||||
NON_MOVEABLE(Sha256Generator);
|
||||
private:
|
||||
using Impl = impl::Sha256Impl;
|
||||
public:
|
||||
static constexpr size_t HashSize = Impl::HashSize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
|
||||
static constexpr inline u8 Asn1Identifier[] = {
|
||||
0x30, 0x31, /* Sequence, size 0x31 */
|
||||
0x30, 0x0D, /* Sequence, size 0x0D */
|
||||
0x06, 0x09, /* Object Identifier */
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* SHA-256 */
|
||||
0x05, 0x00, /* Null */
|
||||
0x04, 0x20, /* Octet string, size 0x20 */
|
||||
};
|
||||
static constexpr size_t Asn1IdentifierSize = util::size(Asn1Identifier);
|
||||
private:
|
||||
Impl m_impl{};
|
||||
public:
|
||||
Sha256Generator() = default;
|
||||
|
||||
void Initialize() {
|
||||
m_impl.Initialize();
|
||||
}
|
||||
|
||||
void Update(const void *data, size_t size) {
|
||||
m_impl.Update(data, size);
|
||||
}
|
||||
|
||||
void GetHash(void *dst, size_t size) {
|
||||
m_impl.GetHash(dst, size);
|
||||
}
|
||||
|
||||
void InitializeWithContext(const Sha256Context *context) {
|
||||
m_impl.InitializeWithContext(context);
|
||||
}
|
||||
|
||||
size_t GetContext(Sha256Context *context) const {
|
||||
return m_impl.GetContext(context);
|
||||
}
|
||||
|
||||
size_t GetBufferedDataSize() const {
|
||||
return m_impl.GetBufferedDataSize();
|
||||
}
|
||||
|
||||
void GetBufferedData(void *dst, size_t dst_size) const {
|
||||
return m_impl.GetBufferedData(dst, dst_size);
|
||||
}
|
||||
};
|
||||
|
||||
void GenerateSha256(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
|
||||
ALWAYS_INLINE void GenerateSha256Hash(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return GenerateSha256(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
template<typename T, typename = typename std::enable_if<std::same_as<T, u8> || std::same_as<T, s8> || std::same_as<T, char> || std::same_as<T, unsigned char>>::type>
|
||||
constexpr ALWAYS_INLINE void GenerateSha256(u8 *dst, size_t dst_size, const T *src, size_t src_size) {
|
||||
if (std::is_constant_evaluated()) {
|
||||
impl::Sha256CompileTimeImpl sha;
|
||||
sha.Initialize();
|
||||
sha.Update(src, src_size);
|
||||
sha.GetHash(dst, dst_size);
|
||||
} else {
|
||||
return GenerateSha256(static_cast<void *>(dst), dst_size, static_cast<const void *>(src), src_size);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_sha3_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
struct Sha3Context {
|
||||
u32 hash_size;
|
||||
u32 buffered_bytes;
|
||||
u64 internal_state[25];
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<size_t HashSize>
|
||||
struct Sha3Asn1IdentifierByte;
|
||||
|
||||
template<> struct Sha3Asn1IdentifierByte<224 / BITSIZEOF(u8)> { static constexpr u8 Value = 0x07; };
|
||||
template<> struct Sha3Asn1IdentifierByte<256 / BITSIZEOF(u8)> { static constexpr u8 Value = 0x08; };
|
||||
template<> struct Sha3Asn1IdentifierByte<384 / BITSIZEOF(u8)> { static constexpr u8 Value = 0x09; };
|
||||
template<> struct Sha3Asn1IdentifierByte<512 / BITSIZEOF(u8)> { static constexpr u8 Value = 0x0A; };
|
||||
|
||||
}
|
||||
|
||||
template <size_t _HashSize>
|
||||
class Sha3Generator {
|
||||
NON_COPYABLE(Sha3Generator);
|
||||
NON_MOVEABLE(Sha3Generator);
|
||||
private:
|
||||
using Impl = impl::Sha3Impl<_HashSize>;
|
||||
public:
|
||||
static constexpr size_t HashSize = Impl::HashSize;
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
|
||||
static constexpr inline u8 Asn1Identifier[] = {
|
||||
0x30, 0x31, /* Sequence, size 0x31 */
|
||||
0x30, 0x0D, /* Sequence, size 0x0D */
|
||||
0x06, 0x09, /* Object Identifier */
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, impl::Sha3Asn1IdentifierByte<HashSize>::Value, /* SHA3-*** */
|
||||
0x05, 0x00, /* Null */
|
||||
0x04, 0x20, /* Octet string, size 0x20 */
|
||||
};
|
||||
static constexpr size_t Asn1IdentifierSize = util::size(Asn1Identifier);
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
Sha3Generator() { /* ... */ }
|
||||
|
||||
void Initialize() {
|
||||
m_impl.Initialize();
|
||||
}
|
||||
|
||||
void Update(const void *data, size_t size) {
|
||||
m_impl.Update(data, size);
|
||||
}
|
||||
|
||||
void GetHash(void *dst, size_t size) {
|
||||
m_impl.GetHash(dst, size);
|
||||
}
|
||||
|
||||
void InitializeWithContext(const Sha3Context *context) {
|
||||
m_impl.InitializeWithContext(context);
|
||||
}
|
||||
|
||||
void GetContext(Sha3Context *context) const {
|
||||
m_impl.GetContext(context);
|
||||
}
|
||||
};
|
||||
|
||||
using Sha3224Generator = Sha3Generator<224 / BITSIZEOF(u8)>;
|
||||
using Sha3256Generator = Sha3Generator<256 / BITSIZEOF(u8)>;
|
||||
using Sha3384Generator = Sha3Generator<384 / BITSIZEOF(u8)>;
|
||||
using Sha3512Generator = Sha3Generator<512 / BITSIZEOF(u8)>;
|
||||
|
||||
inline void GenerateSha3224(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
Sha3224Generator generator;
|
||||
|
||||
generator.Initialize();
|
||||
generator.Update(src, src_size);
|
||||
generator.GetHash(dst, dst_size);
|
||||
}
|
||||
|
||||
inline void GenerateSha3256(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
Sha3256Generator generator;
|
||||
|
||||
generator.Initialize();
|
||||
generator.Update(src, src_size);
|
||||
generator.GetHash(dst, dst_size);
|
||||
}
|
||||
|
||||
inline void GenerateSha3384(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
Sha3384Generator generator;
|
||||
|
||||
generator.Initialize();
|
||||
generator.Update(src, src_size);
|
||||
generator.GetHash(dst, dst_size);
|
||||
}
|
||||
|
||||
inline void GenerateSha3512(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
Sha3512Generator generator;
|
||||
|
||||
generator.Initialize();
|
||||
generator.Update(src, src_size);
|
||||
generator.GetHash(dst, dst_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_xts_mode_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
/* TODO: C++20 BlockCipher concept */
|
||||
|
||||
template<typename BlockCipher>
|
||||
class XtsDecryptor {
|
||||
NON_COPYABLE(XtsDecryptor);
|
||||
NON_MOVEABLE(XtsDecryptor);
|
||||
private:
|
||||
using Impl = impl::XtsModeImpl;
|
||||
public:
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
static constexpr size_t IvSize = Impl::IvSize;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
XtsDecryptor() { /* ... */ }
|
||||
|
||||
template<typename BlockCipher2>
|
||||
void Initialize(const BlockCipher *cipher1, const BlockCipher2 *cipher2, const void *iv, size_t iv_size) {
|
||||
m_impl.InitializeDecryption(cipher1, cipher2, iv, iv_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_impl.template Update<BlockCipher>(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
size_t Finalize(void *dst, size_t dst_size) {
|
||||
return m_impl.FinalizeDecryption(dst, dst_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_xts_mode_impl.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
/* TODO: C++20 BlockCipher concept */
|
||||
|
||||
template<typename BlockCipher>
|
||||
class XtsEncryptor {
|
||||
NON_COPYABLE(XtsEncryptor);
|
||||
NON_MOVEABLE(XtsEncryptor);
|
||||
private:
|
||||
using Impl = impl::XtsModeImpl;
|
||||
public:
|
||||
static constexpr size_t BlockSize = Impl::BlockSize;
|
||||
static constexpr size_t IvSize = Impl::IvSize;
|
||||
private:
|
||||
Impl m_impl;
|
||||
public:
|
||||
XtsEncryptor() { /* ... */ }
|
||||
|
||||
template<typename BlockCipher2>
|
||||
void Initialize(const BlockCipher *cipher1, const BlockCipher2 *cipher2, const void *iv, size_t iv_size) {
|
||||
m_impl.InitializeEncryption(cipher1, cipher2, iv, iv_size);
|
||||
}
|
||||
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return m_impl.template Update<BlockCipher>(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
size_t Finalize(void *dst, size_t dst_size) {
|
||||
return m_impl.FinalizeEncryption(dst, dst_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_block_cipher.hpp>
|
||||
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<size_t _KeySize>
|
||||
class AesImpl {
|
||||
public:
|
||||
static constexpr size_t KeySize = _KeySize;
|
||||
static constexpr size_t BlockSize = 16;
|
||||
static constexpr s32 RoundCount = (KeySize / 4) + 6;
|
||||
static constexpr size_t RoundKeySize = BlockSize * (RoundCount + 1);
|
||||
private:
|
||||
#ifdef ATMOSPHERE_IS_EXOSPHERE
|
||||
int m_slot;
|
||||
#endif
|
||||
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
||||
u32 m_round_keys[RoundKeySize / sizeof(u32)];
|
||||
#endif
|
||||
public:
|
||||
~AesImpl();
|
||||
|
||||
void Initialize(const void *key, size_t key_size, bool is_encrypt);
|
||||
void EncryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const;
|
||||
void DecryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const;
|
||||
|
||||
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
||||
const u8 *GetRoundKey() const {
|
||||
return reinterpret_cast<const u8 *>(m_round_keys);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
static_assert(BlockCipher<AesImpl<16>>);
|
||||
static_assert(BlockCipher<AesImpl<24>>);
|
||||
static_assert(BlockCipher<AesImpl<32>>);
|
||||
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_memory_compare.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
class BigNum {
|
||||
NON_COPYABLE(BigNum);
|
||||
NON_MOVEABLE(BigNum);
|
||||
public:
|
||||
using HalfWord = u16;
|
||||
using Word = u32;
|
||||
using DoubleWord = u64;
|
||||
|
||||
static constexpr size_t MaxBits = 4096;
|
||||
static constexpr size_t BitsPerWord = sizeof(Word) * CHAR_BIT;
|
||||
static constexpr Word MaxWord = std::numeric_limits<Word>::max();
|
||||
static constexpr Word MaxHalfWord = std::numeric_limits<HalfWord>::max();
|
||||
|
||||
class WordAllocator {
|
||||
NON_COPYABLE(WordAllocator);
|
||||
NON_MOVEABLE(WordAllocator);
|
||||
public:
|
||||
class Allocation {
|
||||
NON_COPYABLE(Allocation);
|
||||
NON_MOVEABLE(Allocation);
|
||||
private:
|
||||
friend class WordAllocator;
|
||||
private:
|
||||
WordAllocator *m_allocator;
|
||||
Word *m_buffer;
|
||||
size_t m_count;
|
||||
private:
|
||||
constexpr ALWAYS_INLINE Allocation(WordAllocator *a, Word *w, size_t c) : m_allocator(a), m_buffer(w), m_count(c) { /* ... */ }
|
||||
public:
|
||||
ALWAYS_INLINE ~Allocation() { if (m_allocator) { m_allocator->Free(m_buffer, m_count); } }
|
||||
|
||||
constexpr ALWAYS_INLINE Word *GetBuffer() const { return m_buffer; }
|
||||
constexpr ALWAYS_INLINE size_t GetCount() const { return m_count; }
|
||||
constexpr ALWAYS_INLINE bool IsValid() const { return m_buffer != nullptr; }
|
||||
};
|
||||
|
||||
friend class Allocation;
|
||||
private:
|
||||
Word *m_buffer;
|
||||
size_t m_count;
|
||||
size_t m_max_count;
|
||||
size_t m_min_count;
|
||||
private:
|
||||
ALWAYS_INLINE void Free(void *words, size_t num) {
|
||||
m_buffer -= num;
|
||||
m_count += num;
|
||||
|
||||
AMS_ASSERT(words == m_buffer);
|
||||
AMS_UNUSED(words);
|
||||
}
|
||||
public:
|
||||
constexpr ALWAYS_INLINE WordAllocator(Word *buf, size_t c) : m_buffer(buf), m_count(c), m_max_count(c), m_min_count(c) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE Allocation Allocate(size_t num) {
|
||||
if (num <= m_count) {
|
||||
Word *allocated = m_buffer;
|
||||
|
||||
m_buffer += num;
|
||||
m_count -= num;
|
||||
m_min_count = std::min(m_count, m_min_count);
|
||||
|
||||
return Allocation(this, allocated, num);
|
||||
} else {
|
||||
return Allocation(nullptr, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE size_t GetMaxUsedSize() const {
|
||||
return (m_max_count - m_min_count) * sizeof(Word);
|
||||
}
|
||||
};
|
||||
private:
|
||||
Word *m_words;
|
||||
size_t m_num_words;
|
||||
size_t m_max_words;
|
||||
private:
|
||||
static void ImportImpl(Word *out, size_t out_size, const u8 *src, size_t src_size);
|
||||
static void ExportImpl(u8 *out, size_t out_size, const Word *src, size_t src_size);
|
||||
public:
|
||||
constexpr BigNum() : m_words(), m_num_words(), m_max_words() { /* ... */ }
|
||||
~BigNum() { /* ... */ }
|
||||
|
||||
constexpr void ReserveStatic(Word *buf, size_t capacity) {
|
||||
m_words = buf;
|
||||
m_max_words = capacity;
|
||||
}
|
||||
|
||||
bool Import(const void *src, size_t src_size);
|
||||
void Export(void *dst, size_t dst_size);
|
||||
|
||||
size_t GetSize() const;
|
||||
|
||||
bool IsZero() const {
|
||||
return m_num_words == 0;
|
||||
}
|
||||
|
||||
bool ExpMod(void *dst, const void *src, size_t size, const BigNum &exp, u32 *work_buf, size_t work_buf_size) const;
|
||||
void ClearToZero();
|
||||
void UpdateCount();
|
||||
public:
|
||||
/* Utility. */
|
||||
static bool IsZero(const Word *w, size_t num_words);
|
||||
static int Compare(const Word *lhs, const Word *rhs, size_t num_words);
|
||||
static size_t CountWords(const Word *w, size_t num_words);
|
||||
static size_t CountSignificantBits(Word w);
|
||||
static void ClearToZero(Word *w, size_t num_words);
|
||||
static void SetToWord(Word *w, size_t num_words, Word v);
|
||||
static void Copy(Word *dst, const Word *src, size_t num_words);
|
||||
|
||||
/* Arithmetic. */
|
||||
static bool ExpMod(Word *dst, const Word *src, const Word *exp, size_t exp_num_words, const Word *mod, size_t mod_num_words, WordAllocator *allocator);
|
||||
static bool MultMod(Word *dst, const Word *src, const Word *mult, const Word *mod, size_t num_words, WordAllocator *allocator);
|
||||
static bool Mod(Word *dst, const Word *src, size_t src_words, const Word *mod, size_t mod_words, WordAllocator *allocator);
|
||||
static bool DivMod(Word *quot, Word *rem, const Word *top, size_t top_words, const Word *bot, size_t bot_words, WordAllocator *allocator);
|
||||
static bool Mult(Word *dst, const Word *lhs, const Word *rhs, size_t num_words, WordAllocator *allocator);
|
||||
|
||||
static Word LeftShift(Word *dst, const Word *w, size_t num_words, const size_t shift);
|
||||
static Word RightShift(Word *dst, const Word *w, size_t num_words, const size_t shift);
|
||||
static Word Add(Word *dst, const Word *lhs, const Word *rhs, size_t num_words);
|
||||
static Word Sub(Word *dst, const Word *lhs, const Word *rhs, size_t num_words);
|
||||
static Word MultAdd(Word *dst, const Word *w, size_t num_words, Word mult);
|
||||
static Word MultSub(Word *dst, const Word *w, const Word *v, size_t num_words, Word mult);
|
||||
};
|
||||
|
||||
template<size_t Bits>
|
||||
class StaticBigNum : public BigNum {
|
||||
public:
|
||||
static constexpr size_t NumBits = Bits;
|
||||
static constexpr size_t NumWords = util::AlignUp(NumBits, BitsPerWord) / BitsPerWord;
|
||||
static constexpr size_t NumBytes = NumWords * sizeof(Word);
|
||||
private:
|
||||
Word m_word_buf[NumWords];
|
||||
public:
|
||||
constexpr StaticBigNum() : m_word_buf() {
|
||||
this->ReserveStatic(m_word_buf, NumWords);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_memory_compare.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<typename T>
|
||||
concept BlockCipher = requires(T &t, const void *cv, void *v, size_t sz, bool b) {
|
||||
{ T::BlockSize } -> std::convertible_to<size_t>;
|
||||
{ t.EncryptBlock(v, sz, cv, sz) } -> std::same_as<void>;
|
||||
{ t.DecryptBlock(v, sz, cv, sz) } -> std::same_as<void>;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
class CbcMacImpl {
|
||||
NON_COPYABLE(CbcMacImpl);
|
||||
NON_MOVEABLE(CbcMacImpl);
|
||||
public:
|
||||
static constexpr size_t BlockSize = 0x10;
|
||||
private:
|
||||
enum State {
|
||||
State_None,
|
||||
State_Initialized,
|
||||
State_Done,
|
||||
};
|
||||
private:
|
||||
u8 m_mac[BlockSize];
|
||||
u8 m_buffer[BlockSize];
|
||||
size_t m_buffered_bytes;
|
||||
const void *m_cipher_context;
|
||||
void (*m_cipher_function)(void *dst, const void *src, const void *ctx);
|
||||
State m_state;
|
||||
public:
|
||||
CbcMacImpl() : m_buffered_bytes(0), m_state(State_None) { /* ... */ }
|
||||
|
||||
~CbcMacImpl() {
|
||||
ClearMemory(this, sizeof(*this));
|
||||
}
|
||||
|
||||
template<typename BlockCipher>
|
||||
void Initialize(const BlockCipher *block_cipher) {
|
||||
static_assert(BlockCipher::BlockSize == BlockSize);
|
||||
|
||||
/* Set our context. */
|
||||
m_cipher_context = block_cipher;
|
||||
m_cipher_function = &EncryptBlockCallback<BlockCipher>;
|
||||
m_buffered_bytes = 0;
|
||||
|
||||
std::memset(m_mac, 0, sizeof(m_mac));
|
||||
|
||||
m_state = State_Initialized;
|
||||
}
|
||||
|
||||
template<typename BlockCipher>
|
||||
void Update(const void *data, size_t size) {
|
||||
this->UpdateGeneric(data, size);
|
||||
}
|
||||
|
||||
template<typename BlockCipher>
|
||||
void ProcessBlocks(const void *data, size_t size) {
|
||||
this->ProcessBlocksGeneric(data, size);
|
||||
}
|
||||
|
||||
size_t GetBlockSize() const {
|
||||
return BlockSize;
|
||||
}
|
||||
|
||||
size_t GetBufferedDataSize() const {
|
||||
return m_buffered_bytes;
|
||||
}
|
||||
|
||||
void UpdateGeneric(const void *data, size_t size);
|
||||
void ProcessBlocksGeneric(const void *data, size_t num_blocks);
|
||||
void ProcessPartialData(const void *data, size_t size);
|
||||
void ProcessRemainingData(const void *data, size_t size);
|
||||
|
||||
void GetMac(void *mac, size_t mac_size);
|
||||
void MaskBufferedData(const void *data, size_t size);
|
||||
private:
|
||||
void ProcessBlock(const void *data);
|
||||
|
||||
template<typename BlockCipher>
|
||||
static void EncryptBlockCallback(void *dst, const void *src, const void *cipher) {
|
||||
static_assert(BlockCipher::BlockSize == BlockSize);
|
||||
static_cast<const BlockCipher *>(cipher)->EncryptBlock(dst, BlockCipher::BlockSize, src, BlockCipher::BlockSize);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
void CbcMacImpl::Update<AesEncryptor128>(const void *data, size_t size);
|
||||
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<typename BlockCipher>
|
||||
class CbcModeImpl {
|
||||
NON_COPYABLE(CbcModeImpl);
|
||||
NON_MOVEABLE(CbcModeImpl);
|
||||
public:
|
||||
static constexpr size_t KeySize = BlockCipher::KeySize;
|
||||
static constexpr size_t BlockSize = BlockCipher::BlockSize;
|
||||
static constexpr size_t IvSize = BlockCipher::BlockSize;
|
||||
private:
|
||||
enum State {
|
||||
State_None,
|
||||
State_Initialized,
|
||||
};
|
||||
private:
|
||||
const BlockCipher *m_block_cipher;
|
||||
u8 m_iv[IvSize];
|
||||
u8 m_buffer[BlockSize];
|
||||
size_t m_buffered_bytes;
|
||||
State m_state;
|
||||
public:
|
||||
CbcModeImpl() : m_state(State_None) { /* ... */ }
|
||||
|
||||
~CbcModeImpl() {
|
||||
ClearMemory(this, sizeof(*this));
|
||||
}
|
||||
|
||||
void Initialize(const BlockCipher *block_cipher, const void *iv, size_t iv_size) {
|
||||
AMS_ASSERT(iv_size == IvSize);
|
||||
AMS_UNUSED(iv_size);
|
||||
|
||||
m_block_cipher = block_cipher;
|
||||
std::memcpy(m_iv, iv, IvSize);
|
||||
m_buffered_bytes = 0;
|
||||
|
||||
m_state = State_Initialized;
|
||||
}
|
||||
|
||||
size_t GetBufferedDataSize() const {
|
||||
return m_buffered_bytes;
|
||||
}
|
||||
|
||||
size_t UpdateEncryption(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
AMS_ASSERT(dst_size >= ((src_size + this->GetBufferedDataSize()) / BlockSize) * BlockSize);
|
||||
AMS_ASSERT(m_state == State_Initialized);
|
||||
|
||||
return this->Update(dst, dst_size, src, src_size, [&] (u8 *d, u8 *i, const u8 *s, size_t n) ALWAYS_INLINE_LAMBDA {
|
||||
this->EncryptBlocks(d, i, s, n);
|
||||
});
|
||||
}
|
||||
|
||||
size_t UpdateDecryption(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
AMS_ASSERT(dst_size >= ((src_size + this->GetBufferedDataSize()) / BlockSize) * BlockSize);
|
||||
AMS_ASSERT(m_state == State_Initialized);
|
||||
|
||||
return this->Update(dst, dst_size, src, src_size, [&] (u8 *d, u8 *i, const u8 *s, size_t n) ALWAYS_INLINE_LAMBDA {
|
||||
this->DecryptBlocks(d, i, s, n);
|
||||
});
|
||||
}
|
||||
private:
|
||||
size_t Update(void *_dst, size_t dst_size, const void *_src, size_t src_size, auto ProcessBlocks) {
|
||||
AMS_UNUSED(dst_size);
|
||||
|
||||
u8 *dst = static_cast<u8 *>(_dst);
|
||||
const u8 *src = static_cast<const u8 *>(_src);
|
||||
size_t remaining = src_size;
|
||||
size_t processed = 0;
|
||||
|
||||
if (m_buffered_bytes > 0) {
|
||||
const size_t copy_size = std::min(BlockSize - m_buffered_bytes, remaining);
|
||||
|
||||
std::memcpy(m_buffer + m_buffered_bytes, src, copy_size);
|
||||
src += copy_size;
|
||||
remaining -= copy_size;
|
||||
m_buffered_bytes += copy_size;
|
||||
|
||||
if (m_buffered_bytes == BlockSize) {
|
||||
ProcessBlocks(dst, m_iv, m_buffer, 1);
|
||||
processed += BlockSize;
|
||||
dst += BlockSize;
|
||||
|
||||
m_buffered_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining >= BlockSize) {
|
||||
const size_t num_blocks = remaining / BlockSize;
|
||||
|
||||
ProcessBlocks(dst, m_iv, src, num_blocks);
|
||||
|
||||
const size_t processed_size = num_blocks * BlockSize;
|
||||
dst += processed_size;
|
||||
src += processed_size;
|
||||
remaining -= processed_size;
|
||||
processed += processed_size;
|
||||
}
|
||||
|
||||
if (remaining > 0) {
|
||||
std::memcpy(m_buffer, src, remaining);
|
||||
m_buffered_bytes = remaining;
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
void EncryptBlocks(u8 *dst, u8 *iv, const u8 *src, size_t num_blocks) {
|
||||
const u8 *cur_iv = iv;
|
||||
|
||||
u8 block[BlockSize];
|
||||
while (num_blocks--) {
|
||||
for (size_t i = 0; i < BlockSize; ++i) {
|
||||
block[i] = src[i] ^ cur_iv[i];
|
||||
}
|
||||
|
||||
m_block_cipher->EncryptBlock(dst, BlockSize, block, BlockSize);
|
||||
|
||||
cur_iv = dst;
|
||||
src += BlockSize;
|
||||
dst += BlockSize;
|
||||
}
|
||||
|
||||
if (iv != cur_iv) {
|
||||
std::memcpy(iv, cur_iv, BlockSize);
|
||||
}
|
||||
}
|
||||
|
||||
void DecryptBlocks(u8 *dst, u8 *iv, const u8 *src, size_t num_blocks) {
|
||||
u8 next_iv[BlockSize];
|
||||
std::memcpy(next_iv, src + ((num_blocks - 1) * BlockSize), BlockSize);
|
||||
|
||||
if (src == dst) {
|
||||
src = src + ((num_blocks - 1) * BlockSize);
|
||||
dst = dst + ((num_blocks - 1) * BlockSize);
|
||||
|
||||
const u8 *cur_iv = (num_blocks == 1) ? iv : src - BlockSize;
|
||||
|
||||
while (num_blocks-- > 1) {
|
||||
m_block_cipher->DecryptBlock(dst, BlockSize, src, BlockSize);
|
||||
|
||||
for (size_t i = 0; i < BlockSize; ++i) {
|
||||
dst[i] ^= cur_iv[i];
|
||||
}
|
||||
|
||||
cur_iv -= BlockSize;
|
||||
src -= BlockSize;
|
||||
dst -= BlockSize;
|
||||
}
|
||||
|
||||
m_block_cipher->DecryptBlock(dst, BlockSize, src, BlockSize);
|
||||
|
||||
for (size_t i = 0; i < BlockSize; ++i) {
|
||||
dst[i] ^= iv[i];
|
||||
}
|
||||
} else {
|
||||
const u8 *cur_iv = iv;
|
||||
|
||||
while (num_blocks-- > 0) {
|
||||
m_block_cipher->DecryptBlock(dst, BlockSize, src, BlockSize);
|
||||
|
||||
for (size_t i = 0; i < BlockSize; ++i) {
|
||||
dst[i] ^= cur_iv[i];
|
||||
}
|
||||
|
||||
cur_iv = src;
|
||||
src += BlockSize;
|
||||
dst += BlockSize;
|
||||
}
|
||||
}
|
||||
|
||||
std::memcpy(iv, next_iv, BlockSize);
|
||||
}
|
||||
};
|
||||
|
||||
/* TODO: Optimized AES cbc impl specializations. */
|
||||
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
#include <vapours/crypto/impl/crypto_ctr_mode_impl.hpp>
|
||||
#include <vapours/crypto/impl/crypto_cbc_mac_impl.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<typename BlockCipher>
|
||||
class CcmModeImpl {
|
||||
NON_COPYABLE(CcmModeImpl);
|
||||
NON_MOVEABLE(CcmModeImpl);
|
||||
public:
|
||||
static constexpr size_t KeySize = BlockCipher::KeySize;
|
||||
static constexpr size_t BlockSize = BlockCipher::BlockSize;
|
||||
private:
|
||||
enum State {
|
||||
State_None,
|
||||
State_ProcessingAad,
|
||||
State_ProcessingData,
|
||||
State_DataInputDone,
|
||||
State_Done,
|
||||
};
|
||||
private:
|
||||
u8 m_mac[BlockSize];
|
||||
s64 m_given_data_size;
|
||||
s64 m_given_aad_size;
|
||||
size_t m_given_mac_size;
|
||||
s64 m_processed_data_size;
|
||||
s64 m_processed_aad_size;
|
||||
State m_state;
|
||||
CtrModeImpl<BlockCipher> m_ctr_mode_impl;
|
||||
CbcMacImpl m_cbc_mac_impl;
|
||||
public:
|
||||
CcmModeImpl() : m_state(State_None) { /* ... */ }
|
||||
|
||||
~CcmModeImpl() {
|
||||
ClearMemory(this, sizeof(*this));
|
||||
}
|
||||
|
||||
void Initialize(const BlockCipher *cipher, const void *nonce, size_t nonce_size, s64 aad_size, s64 data_size, size_t mac_size) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(7 <= nonce_size && nonce_size <= 13);
|
||||
AMS_ASSERT(4 <= mac_size && mac_size <= 16 && (mac_size % 2) == 0);
|
||||
AMS_ASSERT(aad_size >= 0);
|
||||
AMS_ASSERT(data_size >= 0);
|
||||
if (nonce_size == 7) {
|
||||
AMS_ASSERT(data_size <= std::numeric_limits<s64>::max());
|
||||
} else {
|
||||
AMS_ASSERT(data_size < (INT64_C(1) << ((15 - nonce_size) * 8)));
|
||||
}
|
||||
|
||||
/* Set various size fields. */
|
||||
m_given_aad_size = aad_size;
|
||||
m_given_data_size = data_size;
|
||||
m_given_mac_size = mac_size;
|
||||
m_processed_aad_size = 0;
|
||||
m_processed_data_size = 0;
|
||||
|
||||
/* Make the initial counter. */
|
||||
u8 tmp[BlockSize];
|
||||
MakeInitialCounter(tmp, nonce, nonce_size);
|
||||
|
||||
/* Encrypt the block. */
|
||||
cipher->EncryptBlock(m_mac, BlockSize, tmp, BlockSize);
|
||||
|
||||
/* Initialize our ctr mode impl. */
|
||||
m_ctr_mode_impl.Initialize(cipher, tmp, BlockSize);
|
||||
m_ctr_mode_impl.IncrementCounter();
|
||||
|
||||
/* Make the header block. */
|
||||
MakeHeaderBlock(tmp, nonce, nonce_size, aad_size, data_size, mac_size);
|
||||
|
||||
/* Initialize our cbc mac impl. */
|
||||
m_cbc_mac_impl.Initialize(cipher);
|
||||
m_cbc_mac_impl.template Update<BlockCipher>(tmp, BlockSize);
|
||||
|
||||
/* Process aad size block. */
|
||||
if (aad_size > 0) {
|
||||
this->ProcessEncodedAadSize();
|
||||
m_state = State_ProcessingAad;
|
||||
} else {
|
||||
m_state = State_ProcessingData;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAad(const void *aad, size_t aad_size) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(m_state == State_ProcessingAad);
|
||||
AMS_ASSERT(m_processed_aad_size + static_cast<s64>(aad_size) <= m_given_aad_size);
|
||||
|
||||
/* Update on the aad. */
|
||||
m_cbc_mac_impl.template Update<BlockCipher>(aad, aad_size);
|
||||
m_processed_aad_size += aad_size;
|
||||
|
||||
/* Check if we're done with aad. */
|
||||
if (m_processed_aad_size == m_given_aad_size) {
|
||||
/* Pad the aad to block size. */
|
||||
this->ProcessPadding();
|
||||
|
||||
/* Update our state. */
|
||||
if (m_given_data_size > 0) {
|
||||
m_state = State_ProcessingData;
|
||||
} else {
|
||||
m_state = State_DataInputDone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t UpdateEncryption(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(m_state == State_ProcessingData);
|
||||
AMS_ASSERT(m_processed_data_size + static_cast<s64>(src_size) <= m_given_data_size);
|
||||
AMS_ASSERT(dst_size >= src_size);
|
||||
|
||||
/* Update mac on decrypted data. */
|
||||
m_cbc_mac_impl.template Update<BlockCipher>(src, src_size);
|
||||
|
||||
/* Encrypt. */
|
||||
const size_t processed = m_ctr_mode_impl.Update(dst, dst_size, src, src_size);
|
||||
m_processed_data_size += src_size;
|
||||
|
||||
/* Check if we're done with data. */
|
||||
if (m_processed_data_size == m_given_data_size) {
|
||||
/* Pad the data to block size. */
|
||||
this->ProcessPadding();
|
||||
|
||||
m_state = State_DataInputDone;
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
size_t UpdateDecryption(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(m_state == State_ProcessingData);
|
||||
AMS_ASSERT(m_processed_data_size + static_cast<s64>(src_size) <= m_given_data_size);
|
||||
AMS_ASSERT(dst_size >= src_size);
|
||||
|
||||
/* Decrypt. */
|
||||
const size_t processed = m_ctr_mode_impl.Update(dst, dst_size, src, src_size);
|
||||
m_processed_data_size += src_size;
|
||||
|
||||
/* Update mac on decrypted data. */
|
||||
m_cbc_mac_impl.template Update<BlockCipher>(dst, dst_size);
|
||||
|
||||
/* Check if we're done with data. */
|
||||
if (m_processed_data_size == m_given_data_size) {
|
||||
/* Pad the data to block size. */
|
||||
this->ProcessPadding();
|
||||
|
||||
m_state = State_DataInputDone;
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
void GetMac(void *mac, size_t mac_size) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(m_state == State_DataInputDone || m_state == State_Done);
|
||||
AMS_ASSERT(mac_size >= m_given_mac_size);
|
||||
AMS_UNUSED(mac_size);
|
||||
|
||||
/* Generate the mac, if we haven't already. */
|
||||
if (m_state == State_DataInputDone) {
|
||||
this->GenerateMac();
|
||||
m_state = State_Done;
|
||||
}
|
||||
|
||||
/* Copy out the mac. */
|
||||
std::memcpy(mac, m_mac, m_given_mac_size);
|
||||
}
|
||||
private:
|
||||
void MakeInitialCounter(void *dst, const void *nonce, size_t nonce_size) {
|
||||
/* Clear the counter. */
|
||||
u8 *ctr = static_cast<u8 *>(dst);
|
||||
std::memset(ctr, 0, BlockSize);
|
||||
|
||||
/* Set the nonce. */
|
||||
ctr[0] = (((BlockSize - 1 - nonce_size) & 0xFF) - 1) & 0x07;
|
||||
std::memcpy(ctr + 1, nonce, nonce_size);
|
||||
}
|
||||
|
||||
void MakeHeaderBlock(void *dst, const void *nonce, size_t nonce_size, s64 aad_size, s64 data_size, size_t mac_size) {
|
||||
/* Clear the block. */
|
||||
u8 *hdr = static_cast<u8 *>(dst);
|
||||
std::memset(hdr, 0, BlockSize);
|
||||
|
||||
/* Encode the flags. */
|
||||
hdr[0] = (((BlockSize - 1 - nonce_size) & 0xFF) - 1) & 0x07;
|
||||
hdr[0] |= (((mac_size - 2) / 2) & 0x07) << 3;
|
||||
hdr[0] |= (aad_size > 0) ? 0x40 : 0x00;
|
||||
|
||||
/* Encode the data size. */
|
||||
for (size_t i = 0; i < sizeof(s64); ++i) {
|
||||
hdr[BlockSize - 1 - i] = static_cast<u64>(data_size) >> (BITSIZEOF(u8) * i);
|
||||
}
|
||||
|
||||
/* Copy the nonce. */
|
||||
std::memcpy(hdr + 1, nonce, nonce_size);
|
||||
}
|
||||
|
||||
void ProcessEncodedAadSize() {
|
||||
u8 encoded_aad[10];
|
||||
size_t encoded_aad_size;
|
||||
|
||||
if (m_given_aad_size < ((1 << 16) - (1 << 8))) {
|
||||
encoded_aad[0] = (m_given_aad_size >> (BITSIZEOF(u8) * 1)) & 0xFF;
|
||||
encoded_aad[1] = (m_given_aad_size >> (BITSIZEOF(u8) * 0)) & 0xFF;
|
||||
encoded_aad_size = 2;
|
||||
} else if (m_given_aad_size <= 0xFFFFFFFFu) {
|
||||
encoded_aad[0] = 0xFF;
|
||||
encoded_aad[1] = 0xFE;
|
||||
encoded_aad[2] = (m_given_aad_size >> (BITSIZEOF(u8) * 3)) & 0xFF;
|
||||
encoded_aad[3] = (m_given_aad_size >> (BITSIZEOF(u8) * 2)) & 0xFF;
|
||||
encoded_aad[4] = (m_given_aad_size >> (BITSIZEOF(u8) * 1)) & 0xFF;
|
||||
encoded_aad[5] = (m_given_aad_size >> (BITSIZEOF(u8) * 0)) & 0xFF;
|
||||
encoded_aad_size = 6;
|
||||
} else {
|
||||
encoded_aad[0] = 0xFF;
|
||||
encoded_aad[1] = 0xFE;
|
||||
encoded_aad[2] = (static_cast<u64>(m_given_aad_size) >> (BITSIZEOF(u8) * 7)) & 0xFF;
|
||||
encoded_aad[3] = (static_cast<u64>(m_given_aad_size) >> (BITSIZEOF(u8) * 6)) & 0xFF;
|
||||
encoded_aad[4] = (static_cast<u64>(m_given_aad_size) >> (BITSIZEOF(u8) * 5)) & 0xFF;
|
||||
encoded_aad[5] = (static_cast<u64>(m_given_aad_size) >> (BITSIZEOF(u8) * 4)) & 0xFF;
|
||||
encoded_aad[6] = (static_cast<u64>(m_given_aad_size) >> (BITSIZEOF(u8) * 3)) & 0xFF;
|
||||
encoded_aad[7] = (static_cast<u64>(m_given_aad_size) >> (BITSIZEOF(u8) * 2)) & 0xFF;
|
||||
encoded_aad[8] = (static_cast<u64>(m_given_aad_size) >> (BITSIZEOF(u8) * 1)) & 0xFF;
|
||||
encoded_aad[9] = (static_cast<u64>(m_given_aad_size) >> (BITSIZEOF(u8) * 0)) & 0xFF;
|
||||
encoded_aad_size = 10;
|
||||
}
|
||||
|
||||
m_cbc_mac_impl.template Update<BlockCipher>(encoded_aad, encoded_aad_size);
|
||||
}
|
||||
|
||||
void ProcessPadding() {
|
||||
/* Process any remaining padding. */
|
||||
if (const auto buffered = m_cbc_mac_impl.GetBufferedDataSize(); buffered > 0) {
|
||||
u8 zeros[BlockSize] = {};
|
||||
m_cbc_mac_impl.template Update<BlockCipher>(zeros, BlockSize - buffered);
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateMac() {
|
||||
/* Get the cbc mac. */
|
||||
u8 tmp[BlockSize];
|
||||
m_cbc_mac_impl.GetMac(tmp, BlockSize);
|
||||
|
||||
/* Xor into our mac. */
|
||||
for (size_t i = 0; i < BlockSize; ++i) {
|
||||
m_mac[i] ^= tmp[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_hash_function.hpp>
|
||||
#include <vapours/crypto/impl/crypto_cbc_mac_impl.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<typename BlockCipher>
|
||||
class CmacImpl {
|
||||
NON_COPYABLE(CmacImpl);
|
||||
NON_MOVEABLE(CmacImpl);
|
||||
public:
|
||||
static constexpr size_t BlockSize = BlockCipher::BlockSize;
|
||||
static constexpr size_t MacSize = BlockSize;
|
||||
static_assert(BlockSize == 0x10); /* TODO: Should this be supported? */
|
||||
private:
|
||||
enum State {
|
||||
State_None = 0,
|
||||
State_Initialized = 1,
|
||||
State_Done = 2,
|
||||
};
|
||||
private:
|
||||
CbcMacImpl m_cbc_mac_impl;
|
||||
u8 m_sub_key[BlockSize];
|
||||
State m_state;
|
||||
public:
|
||||
CmacImpl() : m_state(State_None) { /* ... */ }
|
||||
~CmacImpl() {
|
||||
/* Clear everything. */
|
||||
ClearMemory(this, sizeof(*this));
|
||||
}
|
||||
|
||||
void Initialize(const BlockCipher *cipher);
|
||||
void Update(const void *data, size_t data_size);
|
||||
void GetMac(void *dst, size_t dst_size);
|
||||
private:
|
||||
static void MultiplyOneOverGF128(u8 *data) {
|
||||
/* Determine the carry bit. */
|
||||
const u8 carry = data[0] & 0x80;
|
||||
|
||||
/* Shift all bytes by one bit. */
|
||||
for (size_t i = 0; i < BlockSize - 1; ++i) {
|
||||
data[i] = (data[i] << 1) | (data[i + 1] >> 7);
|
||||
}
|
||||
data[BlockSize - 1] <<= 1;
|
||||
|
||||
/* Adjust based on carry. */
|
||||
if (carry) {
|
||||
data[BlockSize - 1] ^= 0x87;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename BlockCipher>
|
||||
inline void CmacImpl<BlockCipher>::Initialize(const BlockCipher *cipher) {
|
||||
/* Clear the key storage. */
|
||||
std::memset(m_sub_key, 0, sizeof(m_sub_key));
|
||||
|
||||
/* Set the key storage. */
|
||||
cipher->EncryptBlock(m_sub_key, BlockSize, m_sub_key, BlockSize);
|
||||
MultiplyOneOverGF128(m_sub_key);
|
||||
|
||||
/* Initialize the cbc-mac impl. */
|
||||
m_cbc_mac_impl.Initialize(cipher);
|
||||
|
||||
/* Mark initialized. */
|
||||
m_state = State_Initialized;
|
||||
}
|
||||
|
||||
template<typename BlockCipher>
|
||||
inline void CmacImpl<BlockCipher>::Update(const void *data, size_t data_size) {
|
||||
AMS_ASSERT(m_state == State_Initialized);
|
||||
|
||||
m_cbc_mac_impl.template Update<BlockCipher>(data, data_size);
|
||||
}
|
||||
|
||||
template<typename BlockCipher>
|
||||
inline void CmacImpl<BlockCipher>::GetMac(void *dst, size_t dst_size) {
|
||||
AMS_ASSERT(m_state == State_Initialized || m_state == State_Done);
|
||||
AMS_ASSERT(dst_size >= MacSize);
|
||||
AMS_UNUSED(dst_size);
|
||||
|
||||
/* If we're not already finalized, get the final mac. */
|
||||
if (m_state == State_Initialized) {
|
||||
/* Process padding as needed. */
|
||||
if (m_cbc_mac_impl.GetBufferedDataSize() != BlockSize) {
|
||||
/* Determine the remaining size. */
|
||||
const size_t remaining = BlockSize - m_cbc_mac_impl.GetBufferedDataSize();
|
||||
|
||||
/* Update with padding. */
|
||||
static constexpr u8 s_padding[BlockSize] = { 0x80, /* ... */ };
|
||||
m_cbc_mac_impl.template Update<BlockCipher>(s_padding, remaining);
|
||||
|
||||
/* Update our subkey. */
|
||||
MultiplyOneOverGF128(m_sub_key);
|
||||
}
|
||||
|
||||
/* Mask the subkey. */
|
||||
m_cbc_mac_impl.MaskBufferedData(m_sub_key, BlockSize);
|
||||
|
||||
/* Set our state as done. */
|
||||
m_state = State_Done;
|
||||
}
|
||||
|
||||
/* Get the mac. */
|
||||
m_cbc_mac_impl.GetMac(dst, dst_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<typename BlockCipher>
|
||||
class CtrModeImpl {
|
||||
NON_COPYABLE(CtrModeImpl);
|
||||
NON_MOVEABLE(CtrModeImpl);
|
||||
public:
|
||||
static constexpr size_t KeySize = BlockCipher::KeySize;
|
||||
static constexpr size_t BlockSize = BlockCipher::BlockSize;
|
||||
static constexpr size_t IvSize = BlockCipher::BlockSize;
|
||||
private:
|
||||
enum State {
|
||||
State_None,
|
||||
State_Initialized,
|
||||
};
|
||||
private:
|
||||
const BlockCipher *m_block_cipher;
|
||||
u8 m_counter[IvSize];
|
||||
u8 m_encrypted_counter[BlockSize];
|
||||
size_t m_buffer_offset;
|
||||
State m_state;
|
||||
public:
|
||||
CtrModeImpl() : m_state(State_None) { /* ... */ }
|
||||
|
||||
~CtrModeImpl() {
|
||||
ClearMemory(this, sizeof(*this));
|
||||
}
|
||||
|
||||
void Initialize(const BlockCipher *block_cipher, const void *iv, size_t iv_size) {
|
||||
this->Initialize(block_cipher, iv, iv_size, 0);
|
||||
}
|
||||
|
||||
void Initialize(const BlockCipher *block_cipher, const void *iv, size_t iv_size, s64 offset) {
|
||||
AMS_ASSERT(iv_size == IvSize);
|
||||
AMS_ASSERT(offset >= 0);
|
||||
|
||||
m_block_cipher = block_cipher;
|
||||
m_state = State_Initialized;
|
||||
|
||||
this->SwitchMessage(iv, iv_size);
|
||||
|
||||
if (offset >= 0) {
|
||||
u64 ctr_offset = offset / BlockSize;
|
||||
if (ctr_offset > 0) {
|
||||
this->IncrementCounter(ctr_offset);
|
||||
}
|
||||
|
||||
if (size_t remaining = static_cast<size_t>(offset % BlockSize); remaining != 0) {
|
||||
m_block_cipher->EncryptBlock(m_encrypted_counter, sizeof(m_encrypted_counter), m_counter, sizeof(m_counter));
|
||||
this->IncrementCounter();
|
||||
|
||||
m_buffer_offset = remaining;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SwitchMessage(const void *iv, size_t iv_size) {
|
||||
AMS_ASSERT(m_state == State_Initialized);
|
||||
AMS_ASSERT(iv_size == IvSize);
|
||||
|
||||
std::memcpy(m_counter, iv, iv_size);
|
||||
m_buffer_offset = 0;
|
||||
}
|
||||
|
||||
void IncrementCounter() {
|
||||
for (s32 i = IvSize - 1; i >= 0; --i) {
|
||||
if (++m_counter[i] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t Update(void *_dst, size_t dst_size, const void *_src, size_t src_size) {
|
||||
AMS_ASSERT(m_state == State_Initialized);
|
||||
AMS_ASSERT(dst_size >= src_size);
|
||||
AMS_UNUSED(dst_size);
|
||||
|
||||
u8 *dst = static_cast<u8 *>(_dst);
|
||||
const u8 *src = static_cast<const u8 *>(_src);
|
||||
size_t remaining = src_size;
|
||||
|
||||
if (m_buffer_offset > 0) {
|
||||
const size_t xor_size = std::min(BlockSize - m_buffer_offset, remaining);
|
||||
|
||||
const u8 *ctr = m_encrypted_counter + m_buffer_offset;
|
||||
for (size_t i = 0; i < xor_size; i++) {
|
||||
dst[i] = src[i] ^ ctr[i];
|
||||
}
|
||||
|
||||
src += xor_size;
|
||||
dst += xor_size;
|
||||
remaining -= xor_size;
|
||||
m_buffer_offset += xor_size;
|
||||
|
||||
if (m_buffer_offset == BlockSize) {
|
||||
m_buffer_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining >= BlockSize) {
|
||||
const size_t num_blocks = remaining / BlockSize;
|
||||
|
||||
this->ProcessBlocks(dst, src, num_blocks);
|
||||
|
||||
const size_t processed_size = num_blocks * BlockSize;
|
||||
dst += processed_size;
|
||||
src += processed_size;
|
||||
remaining -= processed_size;
|
||||
}
|
||||
|
||||
if (remaining > 0) {
|
||||
this->ProcessBlock(dst, src, remaining);
|
||||
m_buffer_offset = remaining;
|
||||
}
|
||||
|
||||
return src_size;
|
||||
}
|
||||
private:
|
||||
void IncrementCounter(u64 count) {
|
||||
u64 _block[IvSize / sizeof(u64)] = {};
|
||||
util::StoreBigEndian(std::addressof(_block[(IvSize / sizeof(u64)) - 1]), count);
|
||||
|
||||
u16 acc = 0;
|
||||
const u8 *block = reinterpret_cast<const u8 *>(_block);
|
||||
for (s32 i = IvSize - 1; i >= 0; --i) {
|
||||
acc += (m_counter[i] + block[i]);
|
||||
m_counter[i] = acc & 0xFF;
|
||||
acc >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessBlock(u8 *dst, const u8 *src, size_t src_size) {
|
||||
m_block_cipher->EncryptBlock(m_encrypted_counter, BlockSize, m_counter, IvSize);
|
||||
this->IncrementCounter();
|
||||
|
||||
for (size_t i = 0; i < src_size; i++) {
|
||||
dst[i] = src[i] ^ m_encrypted_counter[i];
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessBlocks(u8 *dst, const u8 *src, size_t num_blocks);
|
||||
};
|
||||
|
||||
template<typename BlockCipher>
|
||||
inline void CtrModeImpl<BlockCipher>::ProcessBlocks(u8 *dst, const u8 *src, size_t num_blocks) {
|
||||
while (num_blocks--) {
|
||||
this->ProcessBlock(dst, src, BlockSize);
|
||||
dst += BlockSize;
|
||||
src += BlockSize;
|
||||
}
|
||||
}
|
||||
|
||||
template<> void CtrModeImpl<AesEncryptor128>::ProcessBlocks(u8 *dst, const u8 *src, size_t num_blocks);
|
||||
|
||||
/* TODO: Optimized x64 CTR-192/256? */
|
||||
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||
template<> void CtrModeImpl<AesEncryptor192>::ProcessBlocks(u8 *dst, const u8 *src, size_t num_blocks);
|
||||
template<> void CtrModeImpl<AesEncryptor256>::ProcessBlocks(u8 *dst, const u8 *src, size_t num_blocks);
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<typename BlockCipher>
|
||||
class GcmModeImpl {
|
||||
NON_COPYABLE(GcmModeImpl);
|
||||
NON_MOVEABLE(GcmModeImpl);
|
||||
public:
|
||||
static constexpr size_t KeySize = BlockCipher::KeySize;
|
||||
static constexpr size_t BlockSize = BlockCipher::BlockSize;
|
||||
static constexpr size_t MacSize = BlockCipher::BlockSize;
|
||||
private:
|
||||
enum State {
|
||||
State_None,
|
||||
State_Initialized,
|
||||
State_ProcessingAad,
|
||||
State_Encrypting,
|
||||
State_Decrypting,
|
||||
State_Done,
|
||||
};
|
||||
|
||||
struct Block128 {
|
||||
u64 hi;
|
||||
u64 lo;
|
||||
|
||||
ALWAYS_INLINE void Clear() {
|
||||
this->hi = 0;
|
||||
this->lo = 0;
|
||||
}
|
||||
};
|
||||
static_assert(util::is_pod<Block128>::value);
|
||||
static_assert(sizeof(Block128) == 0x10);
|
||||
|
||||
union Block {
|
||||
Block128 block_128;
|
||||
u32 block_32[4];
|
||||
u8 block_8[16];
|
||||
};
|
||||
static_assert(util::is_pod<Block>::value);
|
||||
static_assert(sizeof(Block) == 0x10);
|
||||
|
||||
using CipherFunction = void (*)(void *dst_block, const void *src_block, const void *ctx);
|
||||
private:
|
||||
State m_state;
|
||||
const BlockCipher *m_block_cipher;
|
||||
CipherFunction m_cipher_func;
|
||||
u8 m_pad[sizeof(u64)];
|
||||
Block m_block_x;
|
||||
Block m_block_y;
|
||||
Block m_block_ek;
|
||||
Block m_block_ek0;
|
||||
Block m_block_tmp;
|
||||
size_t m_aad_size;
|
||||
size_t m_msg_size;
|
||||
u32 m_aad_remaining;
|
||||
u32 m_msg_remaining;
|
||||
u32 m_counter;
|
||||
Block m_h_mult_blocks[16];
|
||||
public:
|
||||
GcmModeImpl() : m_state(State_None) { /* ... */ }
|
||||
|
||||
~GcmModeImpl() {
|
||||
ClearMemory(this, sizeof(*this));
|
||||
}
|
||||
|
||||
void Initialize(const BlockCipher *block_cipher);
|
||||
|
||||
void Reset(const void *iv, size_t iv_size);
|
||||
|
||||
void UpdateAad(const void *aad, size_t aad_size);
|
||||
size_t UpdateEncrypt(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
size_t UpdateDecrypt(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
|
||||
void GetMac(void *dst, size_t dst_size);
|
||||
private:
|
||||
static void ProcessBlock(void *dst_block, const void *src_block, const void *ctx) {
|
||||
static_cast<const BlockCipher *>(ctx)->EncryptBlock(dst_block, BlockSize, src_block, BlockSize);
|
||||
}
|
||||
|
||||
void InitializeHashKey();
|
||||
void ComputeMac(bool encrypt);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_memory_compare.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<typename T>
|
||||
concept HashFunction = requires(T &t, const void *cv, void *v, size_t sz) {
|
||||
{ T::HashSize } -> std::convertible_to<size_t>;
|
||||
{ T::BlockSize } -> std::convertible_to<size_t>;
|
||||
{ t.Initialize() } -> std::same_as<void>;
|
||||
{ t.Update(cv, sz) } -> std::same_as<void>;
|
||||
{ t.GetHash(v, sz) } -> std::same_as<void>;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_hash_function.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<HashFunction Hash>
|
||||
class HmacImpl {
|
||||
NON_COPYABLE(HmacImpl);
|
||||
NON_MOVEABLE(HmacImpl);
|
||||
public:
|
||||
static constexpr size_t MacSize = Hash::HashSize;
|
||||
static constexpr size_t BlockSize = Hash::BlockSize;
|
||||
private:
|
||||
static constexpr u32 IpadMagic = 0x36363636;
|
||||
static constexpr u32 OpadMagic = 0x5c5c5c5c;
|
||||
|
||||
static constexpr u32 IpadMagicXorOpadMagic = IpadMagic ^ OpadMagic;
|
||||
static_assert(IpadMagicXorOpadMagic == 0x6a6a6a6a);
|
||||
private:
|
||||
enum State {
|
||||
State_None = 0,
|
||||
State_Initialized = 1,
|
||||
State_Done = 2,
|
||||
};
|
||||
private:
|
||||
Hash m_hash_function;
|
||||
u32 m_key[BlockSize / sizeof(u32)];
|
||||
u32 m_mac[MacSize / sizeof(u32)];
|
||||
State m_state;
|
||||
public:
|
||||
HmacImpl() : m_state(State_None) { /* ... */ }
|
||||
~HmacImpl() {
|
||||
static_assert(AMS_OFFSETOF(HmacImpl, m_hash_function) == 0);
|
||||
|
||||
/* Clear everything except for the hash function. */
|
||||
ClearMemory(reinterpret_cast<u8 *>(this) + sizeof(m_hash_function), sizeof(*this) - sizeof(m_hash_function));
|
||||
}
|
||||
|
||||
void Initialize(const void *key, size_t key_size);
|
||||
void Update(const void *data, size_t data_size);
|
||||
void GetMac(void *dst, size_t dst_size);
|
||||
};
|
||||
|
||||
template<HashFunction Hash>
|
||||
inline void HmacImpl<Hash>::Initialize(const void *key, size_t key_size) {
|
||||
/* Clear the key storage. */
|
||||
std::memset(m_key, 0, sizeof(m_key));
|
||||
|
||||
/* Set the key storage. */
|
||||
if (key_size > BlockSize) {
|
||||
m_hash_function.Initialize();
|
||||
m_hash_function.Update(key, key_size);
|
||||
m_hash_function.GetHash(m_key, m_hash_function.HashSize);
|
||||
} else {
|
||||
std::memcpy(m_key, key, key_size);
|
||||
}
|
||||
|
||||
/* Xor the key with the ipad. */
|
||||
for (size_t i = 0; i < util::size(m_key); i++) {
|
||||
m_key[i] ^= IpadMagic;
|
||||
}
|
||||
|
||||
/* Update the hash function with the xor'd key. */
|
||||
m_hash_function.Initialize();
|
||||
m_hash_function.Update(m_key, BlockSize);
|
||||
|
||||
/* Mark initialized. */
|
||||
m_state = State_Initialized;
|
||||
}
|
||||
|
||||
template<HashFunction Hash>
|
||||
inline void HmacImpl<Hash>::Update(const void *data, size_t data_size) {
|
||||
AMS_ASSERT(m_state == State_Initialized);
|
||||
|
||||
m_hash_function.Update(data, data_size);
|
||||
}
|
||||
|
||||
template<HashFunction Hash>
|
||||
inline void HmacImpl<Hash>::GetMac(void *dst, size_t dst_size) {
|
||||
AMS_ASSERT(m_state == State_Initialized || m_state == State_Done);
|
||||
AMS_ASSERT(dst_size >= MacSize);
|
||||
AMS_UNUSED(dst_size);
|
||||
|
||||
/* If we're not already finalized, get the final mac. */
|
||||
if (m_state == State_Initialized) {
|
||||
/* Get the hash of ((key ^ ipad) || data). */
|
||||
m_hash_function.GetHash(m_mac, MacSize);
|
||||
|
||||
/* Xor the key with the opad. */
|
||||
for (size_t i = 0; i < util::size(m_key); i++) {
|
||||
m_key[i] ^= IpadMagicXorOpadMagic;
|
||||
}
|
||||
|
||||
/* Calculate the final mac as hash of ((key ^ opad) || hash((key ^ ipad) || data)) */
|
||||
m_hash_function.Initialize();
|
||||
m_hash_function.Update(m_key, BlockSize);
|
||||
m_hash_function.Update(m_mac, MacSize);
|
||||
m_hash_function.GetHash(m_mac, MacSize);
|
||||
|
||||
/* Set our state as done. */
|
||||
m_state = State_Done;
|
||||
}
|
||||
|
||||
std::memcpy(dst, m_mac, MacSize);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_hash_function.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
class Md5Impl {
|
||||
public:
|
||||
static constexpr size_t HashSize = 0x10;
|
||||
static constexpr size_t BlockSize = 0x40;
|
||||
private:
|
||||
enum State {
|
||||
State_None = 0,
|
||||
State_Initialized = 1,
|
||||
State_Done = 2,
|
||||
};
|
||||
private:
|
||||
union {
|
||||
struct {
|
||||
u32 a, b, c, d;
|
||||
} p;
|
||||
u32 state[4];
|
||||
} m_x;
|
||||
alignas(8) u8 m_y[BlockSize];
|
||||
size_t m_size;
|
||||
State m_state;
|
||||
public:
|
||||
Md5Impl() : m_state(State_None) { /* ... */ }
|
||||
~Md5Impl() { ClearMemory(this, sizeof(*this)); }
|
||||
|
||||
void Initialize();
|
||||
void Update(const void *data, size_t size);
|
||||
void GetHash(void *dst, size_t size);
|
||||
private:
|
||||
void ProcessBlock();
|
||||
void ProcessLastBlock();
|
||||
};
|
||||
|
||||
static_assert(HashFunction<Md5Impl>);
|
||||
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_hash_function.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<HashFunction Hash>
|
||||
class RsaOaepImpl {
|
||||
NON_COPYABLE(RsaOaepImpl);
|
||||
NON_MOVEABLE(RsaOaepImpl);
|
||||
public:
|
||||
static constexpr size_t HashSize = Hash::HashSize;
|
||||
private:
|
||||
static constexpr u8 HeadMagic = 0x00;
|
||||
private:
|
||||
static void ComputeHashWithPadding(void *dst, Hash *hash, const void *salt, size_t salt_size) {
|
||||
/* Initialize our buffer. */
|
||||
u8 buf[8 + HashSize];
|
||||
std::memset(buf, 0, 8);
|
||||
hash->GetHash(buf + 8, HashSize);
|
||||
ON_SCOPE_EXIT { ClearMemory(buf, sizeof(buf)); };
|
||||
|
||||
|
||||
/* Calculate our hash. */
|
||||
hash->Initialize();
|
||||
hash->Update(buf, sizeof(buf));
|
||||
hash->Update(salt, salt_size);
|
||||
hash->GetHash(dst, HashSize);
|
||||
}
|
||||
|
||||
static void ApplyMGF1(u8 *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
u8 buf[HashSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(buf, sizeof(buf)); };
|
||||
|
||||
const size_t required_iters = (dst_size + HashSize - 1) / HashSize;
|
||||
for (size_t i = 0; i < required_iters; i++) {
|
||||
Hash hash;
|
||||
hash.Initialize();
|
||||
hash.Update(src, src_size);
|
||||
|
||||
const u32 tmp = util::ConvertToBigEndian(static_cast<u32>(i));
|
||||
hash.Update(std::addressof(tmp), sizeof(tmp));
|
||||
|
||||
hash.GetHash(buf, HashSize);
|
||||
|
||||
const size_t start = HashSize * i;
|
||||
const size_t end = std::min(dst_size, start + HashSize);
|
||||
for (size_t j = start; j < end; j++) {
|
||||
dst[j] ^= buf[j - start];
|
||||
}
|
||||
}
|
||||
}
|
||||
public:
|
||||
RsaOaepImpl() { /* ... */ }
|
||||
|
||||
void Encode(void *dst, size_t dst_size, Hash *hash, const void *src, size_t src_size, const void *salt, size_t salt_size) {
|
||||
u8 label_digest[HashSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(label_digest, HashSize); };
|
||||
|
||||
hash->GetHash(label_digest, HashSize);
|
||||
return this->Encode(dst, dst_size, label_digest, sizeof(label_digest), src, src_size, salt, salt_size);
|
||||
}
|
||||
|
||||
void Encode(void *dst, size_t dst_size, const void *label_digest, size_t label_digest_size, const void *src, size_t src_size, const void *salt, size_t salt_size) {
|
||||
/* Check our preconditions. */
|
||||
AMS_ASSERT(dst_size >= 2 * HashSize + 2 + src_size);
|
||||
AMS_ASSERT(salt_size > 0);
|
||||
AMS_ASSERT(salt_size == HashSize);
|
||||
AMS_ASSERT(label_digest_size == HashSize);
|
||||
AMS_UNUSED(salt_size, label_digest_size);
|
||||
|
||||
u8 *buf = static_cast<u8 *>(dst);
|
||||
buf[0] = HeadMagic;
|
||||
|
||||
u8 *seed = buf + 1;
|
||||
std::memcpy(seed, salt, HashSize);
|
||||
|
||||
u8 *db = seed + HashSize;
|
||||
std::memcpy(db, label_digest, HashSize);
|
||||
std::memset(db + HashSize, 0, dst_size - 2 * HashSize - 2 - src_size);
|
||||
|
||||
u8 *msg = buf + dst_size - src_size - 1;
|
||||
*(msg++) = 0x01;
|
||||
std::memcpy(msg, src, src_size);
|
||||
|
||||
ApplyMGF1(db, dst_size - (1 + HashSize), seed, HashSize);
|
||||
ApplyMGF1(seed, HashSize, db, dst_size - (1 + HashSize));
|
||||
}
|
||||
|
||||
size_t Decode(void *dst, size_t dst_size, const void *label_digest, size_t label_digest_size, u8 *buf, size_t buf_size) {
|
||||
/* Check our preconditions. */
|
||||
AMS_ABORT_UNLESS(dst_size > 0);
|
||||
AMS_ABORT_UNLESS(buf_size >= 2 * HashSize + 3);
|
||||
AMS_ABORT_UNLESS(label_digest_size == HashSize);
|
||||
AMS_UNUSED(label_digest_size);
|
||||
|
||||
/* Validate sanity byte. */
|
||||
bool is_valid = buf[0] == HeadMagic;
|
||||
|
||||
/* Decrypt seed and masked db. */
|
||||
size_t db_len = buf_size - HashSize - 1;
|
||||
u8 *seed = buf + 1;
|
||||
u8 *db = seed + HashSize;
|
||||
ApplyMGF1(seed, HashSize, db, db_len);
|
||||
ApplyMGF1(db, db_len, seed, HashSize);
|
||||
|
||||
/* Check the label digest. */
|
||||
is_valid &= IsSameBytes(label_digest, db, HashSize);
|
||||
|
||||
/* Skip past the label digest. */
|
||||
db += HashSize;
|
||||
db_len -= HashSize;
|
||||
|
||||
/* Verify that DB is of the form 0000...0001 < message > */
|
||||
s32 msg_ofs = 0;
|
||||
{
|
||||
int looking_for_one = 1;
|
||||
int invalid_db_padding = 0;
|
||||
int is_zero;
|
||||
int is_one;
|
||||
for (size_t i = 0; i < db_len; /* ... */) {
|
||||
is_zero = (db[i] == 0);
|
||||
is_one = (db[i] == 1);
|
||||
msg_ofs += (looking_for_one & is_one) * (static_cast<s32>(++i));
|
||||
looking_for_one &= ~is_one;
|
||||
invalid_db_padding |= (looking_for_one & ~is_zero);
|
||||
}
|
||||
|
||||
is_valid &= (invalid_db_padding == 0);
|
||||
}
|
||||
|
||||
/* If we're invalid, return zero size. */
|
||||
const size_t valid_msg_size = db_len - msg_ofs;
|
||||
const size_t msg_size = std::min(dst_size, static_cast<size_t>(is_valid) * valid_msg_size);
|
||||
|
||||
/* Copy to output. */
|
||||
std::memcpy(dst, db + msg_ofs, msg_size);
|
||||
|
||||
/* Return copied size. */
|
||||
return msg_size;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_hash_function.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<HashFunction Hash>
|
||||
class RsaPkcs1Impl {
|
||||
NON_COPYABLE(RsaPkcs1Impl);
|
||||
NON_MOVEABLE(RsaPkcs1Impl);
|
||||
public:
|
||||
static constexpr size_t HashSize = Hash::HashSize;
|
||||
public:
|
||||
RsaPkcs1Impl() { /* ... */ }
|
||||
~RsaPkcs1Impl() { /* ... */ }
|
||||
|
||||
void BuildPad(void *out_block, size_t block_size, Hash *hash) {
|
||||
AMS_ASSERT(block_size >= 2 + 1 + sizeof(Hash::Asn1Identifier) + HashSize);
|
||||
|
||||
u8 *dst = static_cast<u8 *>(out_block);
|
||||
*(dst++) = 0x00;
|
||||
*(dst++) = 0x01;
|
||||
|
||||
const size_t pad_len = block_size - (2 + 1 + sizeof(Hash::Asn1Identifier) + HashSize);
|
||||
std::memset(dst, 0xFF, pad_len);
|
||||
dst += pad_len;
|
||||
|
||||
*(dst++) = 0x00;
|
||||
|
||||
std::memcpy(dst, Hash::Asn1Identifier, sizeof(Hash::Asn1Identifier));
|
||||
dst += sizeof(Hash::Asn1Identifier);
|
||||
|
||||
hash->GetHash(dst, HashSize);
|
||||
}
|
||||
|
||||
bool CheckPad(const u8 *src, size_t block_size, Hash *hash) {
|
||||
/* Check that block size is minimally big enough. */
|
||||
if (block_size < 2 + 1 + sizeof(Hash::Asn1Identifier) + HashSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check that the padding if correctly of form 0001FF..FF00 */
|
||||
if (*(src++) != 0x00) {
|
||||
return false;
|
||||
}
|
||||
if (*(src++) != 0x01) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t pad_len = block_size - (2 + 1 + sizeof(Hash::Asn1Identifier) + HashSize);
|
||||
for (size_t i = 0; i < pad_len; ++i) {
|
||||
if (*(src++) != 0xFF) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (*(src++) != 0x00) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check that the asn1 identifier matches. */
|
||||
if (std::memcmp(src, Hash::Asn1Identifier, sizeof(Hash::Asn1Identifier)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
src += sizeof(Hash::Asn1Identifier);
|
||||
|
||||
/* Check the hash. */
|
||||
u8 calc_hash[HashSize];
|
||||
hash->GetHash(calc_hash, sizeof(calc_hash));
|
||||
|
||||
return std::memcmp(calc_hash, src, HashSize) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_hash_function.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<HashFunction Hash>
|
||||
class RsaPssImpl {
|
||||
NON_COPYABLE(RsaPssImpl);
|
||||
NON_MOVEABLE(RsaPssImpl);
|
||||
public:
|
||||
static constexpr size_t HashSize = Hash::HashSize;
|
||||
private:
|
||||
static constexpr u8 TailMagic = 0xBC;
|
||||
private:
|
||||
static void ComputeHashWithPadding(void *dst, const u8 *user_hash, size_t user_hash_size, const void *salt, size_t salt_size) {
|
||||
AMS_ASSERT(user_hash_size == HashSize);
|
||||
AMS_UNUSED(user_hash_size);
|
||||
|
||||
/* Initialize our buffer. */
|
||||
u8 buf[8 + HashSize];
|
||||
std::memset(buf, 0, 8);
|
||||
std::memcpy(buf + 8, user_hash, HashSize);
|
||||
ON_SCOPE_EXIT { ClearMemory(buf, sizeof(buf)); };
|
||||
|
||||
|
||||
/* Calculate our hash. */
|
||||
Hash hash;
|
||||
hash.Initialize();
|
||||
hash.Update(buf, sizeof(buf));
|
||||
hash.Update(salt, salt_size);
|
||||
hash.GetHash(dst, HashSize);
|
||||
}
|
||||
|
||||
static void ApplyMGF1(u8 *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
u8 buf[HashSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(buf, sizeof(buf)); };
|
||||
|
||||
const size_t required_iters = (dst_size + HashSize - 1) / HashSize;
|
||||
for (size_t i = 0; i < required_iters; i++) {
|
||||
Hash hash;
|
||||
hash.Initialize();
|
||||
hash.Update(src, src_size);
|
||||
|
||||
const u32 tmp = util::ConvertToBigEndian(static_cast<u32>(i));
|
||||
hash.Update(std::addressof(tmp), sizeof(tmp));
|
||||
|
||||
hash.GetHash(buf, HashSize);
|
||||
|
||||
const size_t start = HashSize * i;
|
||||
const size_t end = std::min(dst_size, start + HashSize);
|
||||
for (size_t j = start; j < end; j++) {
|
||||
dst[j] ^= buf[j - start];
|
||||
}
|
||||
}
|
||||
}
|
||||
public:
|
||||
RsaPssImpl() { /* ... */ }
|
||||
|
||||
bool Verify(u8 *buf, size_t size, const u8 *hash, size_t hash_size) {
|
||||
/* Validate sanity byte. */
|
||||
bool is_valid = buf[size - 1] == TailMagic;
|
||||
|
||||
/* Decrypt maskedDB */
|
||||
const size_t db_len = size - HashSize - 1;
|
||||
u8 *db = buf;
|
||||
u8 *h = db + db_len;
|
||||
ApplyMGF1(db, db_len, h, HashSize);
|
||||
|
||||
/* Apply lmask. */
|
||||
db[0] &= 0x7F;
|
||||
|
||||
/* Verify that DB is of the form 0000...0001 */
|
||||
s32 salt_ofs = 0;
|
||||
{
|
||||
int looking_for_one = 1;
|
||||
int invalid_db_padding = 0;
|
||||
int is_zero;
|
||||
int is_one;
|
||||
for (size_t i = 0; i < db_len; /* ... */) {
|
||||
is_zero = (db[i] == 0);
|
||||
is_one = (db[i] == 1);
|
||||
salt_ofs += (looking_for_one & is_one) * (static_cast<s32>(++i));
|
||||
looking_for_one &= ~is_one;
|
||||
invalid_db_padding |= (looking_for_one & ~is_zero);
|
||||
}
|
||||
|
||||
is_valid &= (invalid_db_padding == 0);
|
||||
}
|
||||
|
||||
/* Verify salt. */
|
||||
const u8 *salt = db + salt_ofs;
|
||||
const size_t salt_size = db_len - salt_ofs;
|
||||
is_valid &= (salt_size != 0);
|
||||
is_valid &= (salt_size != db_len);
|
||||
|
||||
/* Verify hash. */
|
||||
u8 cmp_hash[HashSize];
|
||||
ON_SCOPE_EXIT { ClearMemory(cmp_hash, sizeof(cmp_hash)); };
|
||||
|
||||
ComputeHashWithPadding(cmp_hash, hash, hash_size, salt, salt_size);
|
||||
is_valid &= IsSameBytes(cmp_hash, h, HashSize);
|
||||
|
||||
/* Succeed if all our checks succeeded. */
|
||||
return is_valid;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_hash_function.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
class Sha1Impl {
|
||||
public:
|
||||
static constexpr size_t HashSize = 0x14;
|
||||
static constexpr size_t BlockSize = 0x40;
|
||||
private:
|
||||
enum State {
|
||||
State_None,
|
||||
State_Initialized,
|
||||
State_Done,
|
||||
};
|
||||
private:
|
||||
u32 m_intermediate_hash[HashSize / sizeof(u32)];
|
||||
u8 m_buffer[BlockSize];
|
||||
size_t m_buffered_bytes;
|
||||
u64 m_bits_consumed;
|
||||
State m_state;
|
||||
public:
|
||||
Sha1Impl() : m_state(State_None) { /* ... */ }
|
||||
~Sha1Impl() {
|
||||
ClearMemory(this, sizeof(*this));
|
||||
}
|
||||
|
||||
void Initialize();
|
||||
void Update(const void *data, size_t size);
|
||||
void GetHash(void *dst, size_t size);
|
||||
private:
|
||||
void ProcessBlock(const void *data);
|
||||
void ProcessBlocks(const u8 *data, size_t block_count);
|
||||
void ProcessLastBlock();
|
||||
};
|
||||
|
||||
static_assert(HashFunction<Sha1Impl>);
|
||||
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_hash_function.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
struct Sha256Context;
|
||||
|
||||
}
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
class Sha256Impl {
|
||||
public:
|
||||
static constexpr size_t HashSize = 0x20;
|
||||
static constexpr size_t BlockSize = 0x40;
|
||||
private:
|
||||
enum State {
|
||||
State_None,
|
||||
State_Initialized,
|
||||
State_Done,
|
||||
};
|
||||
private:
|
||||
u32 m_intermediate_hash[HashSize / sizeof(u32)];
|
||||
u8 m_buffer[BlockSize];
|
||||
size_t m_buffered_bytes;
|
||||
u64 m_bits_consumed;
|
||||
State m_state;
|
||||
public:
|
||||
Sha256Impl() : m_state(State_None) { /* ... */ }
|
||||
~Sha256Impl() {
|
||||
ClearMemory(this, sizeof(*this));
|
||||
}
|
||||
|
||||
void Initialize();
|
||||
void Update(const void *data, size_t size);
|
||||
void GetHash(void *dst, size_t size);
|
||||
|
||||
void InitializeWithContext(const Sha256Context *context);
|
||||
size_t GetContext(Sha256Context *context) const;
|
||||
|
||||
size_t GetBufferedDataSize() const { return m_buffered_bytes; }
|
||||
|
||||
void GetBufferedData(void *dst, size_t dst_size) const {
|
||||
AMS_ASSERT(dst_size >= this->GetBufferedDataSize());
|
||||
AMS_UNUSED(dst_size);
|
||||
|
||||
std::memcpy(dst, m_buffer, m_buffered_bytes);
|
||||
}
|
||||
private:
|
||||
void ProcessBlock(const void *data);
|
||||
void ProcessBlocks(const u8 *data, size_t block_count);
|
||||
void ProcessLastBlock();
|
||||
};
|
||||
|
||||
static_assert(HashFunction<Sha256Impl>);
|
||||
|
||||
}
|
||||
@@ -1,296 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
class Sha256CompileTimeImpl {
|
||||
public:
|
||||
static constexpr size_t HashSize = 0x20;
|
||||
static constexpr size_t BlockSize = 0x40;
|
||||
private:
|
||||
enum State {
|
||||
State_None,
|
||||
State_Initialized,
|
||||
State_Done,
|
||||
};
|
||||
private:
|
||||
u32 m_intermediate_hash[HashSize / sizeof(u32)];
|
||||
u8 m_buffer[BlockSize];
|
||||
size_t m_buffered_bytes;
|
||||
u64 m_bits_consumed;
|
||||
State m_state;
|
||||
public:
|
||||
constexpr Sha256CompileTimeImpl() : m_intermediate_hash(), m_buffer(), m_buffered_bytes(), m_bits_consumed(), m_state(State_None) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
constexpr void Initialize() {
|
||||
/* Reset buffered bytes/bits. */
|
||||
m_buffered_bytes = 0;
|
||||
m_bits_consumed = 0;
|
||||
|
||||
/* Set intermediate hash. */
|
||||
m_intermediate_hash[0] = 0x6A09E667;
|
||||
m_intermediate_hash[1] = 0xBB67AE85;
|
||||
m_intermediate_hash[2] = 0x3C6EF372;
|
||||
m_intermediate_hash[3] = 0xA54FF53A;
|
||||
m_intermediate_hash[4] = 0x510E527F;
|
||||
m_intermediate_hash[5] = 0x9B05688C;
|
||||
m_intermediate_hash[6] = 0x1F83D9AB;
|
||||
m_intermediate_hash[7] = 0x5BE0CD19;
|
||||
|
||||
/* Set state. */
|
||||
m_state = State_Initialized;
|
||||
}
|
||||
|
||||
template<typename T, typename = typename std::enable_if<std::same_as<T, u8> || std::same_as<T, s8> || std::same_as<T, char> || std::same_as<T, unsigned char>>::type>
|
||||
constexpr void Update(const T *data, size_t size) {
|
||||
static_assert(sizeof(T) == 1);
|
||||
|
||||
/* Verify we're in a state to update. */
|
||||
AMS_ASSERT(m_state == State_Initialized);
|
||||
|
||||
/* Advance our input bit count. */
|
||||
m_bits_consumed += BITSIZEOF(u8) * (((m_buffered_bytes + size) / BlockSize) * BlockSize);
|
||||
|
||||
/* Process anything we have buffered. */
|
||||
size_t remaining = size;
|
||||
|
||||
if (m_buffered_bytes > 0) {
|
||||
const size_t copy_size = std::min(BlockSize - m_buffered_bytes, remaining);
|
||||
for (size_t i = 0; i < copy_size; ++i) {
|
||||
m_buffer[m_buffered_bytes + i] = static_cast<u8>(data[i]);
|
||||
}
|
||||
|
||||
data += copy_size;
|
||||
remaining -= copy_size;
|
||||
m_buffered_bytes += copy_size;
|
||||
|
||||
/* Process a block, if we filled one. */
|
||||
if (m_buffered_bytes == BlockSize) {
|
||||
this->ProcessBlock(m_buffer);
|
||||
m_buffered_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process blocks, if we have any. */
|
||||
while (remaining >= BlockSize) {
|
||||
u8 block[BlockSize] = {};
|
||||
for (size_t i = 0; i < BlockSize; ++i) {
|
||||
block[i] = static_cast<u8>(data[i]);
|
||||
}
|
||||
this->ProcessBlock(block);
|
||||
|
||||
data += BlockSize;
|
||||
remaining -= BlockSize;
|
||||
}
|
||||
|
||||
/* Copy any leftover data to our buffer. */
|
||||
if (remaining > 0) {
|
||||
m_buffered_bytes = remaining;
|
||||
for (size_t i = 0; i < remaining; ++i) {
|
||||
m_buffer[i] = static_cast<u8>(data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void GetHash(u8 *dst, size_t size) {
|
||||
/* Verify we're in a state to get hash. */
|
||||
AMS_ASSERT(m_state == State_Initialized || m_state == State_Done);
|
||||
AMS_ASSERT(size >= HashSize);
|
||||
AMS_UNUSED(size);
|
||||
|
||||
/* If we need to, process the last block. */
|
||||
if (m_state == State_Initialized) {
|
||||
this->ProcessLastBlock();
|
||||
m_state = State_Done;
|
||||
}
|
||||
|
||||
/* Copy the output hash. */
|
||||
for (size_t i = 0; i < HashSize / sizeof(u32); ++i) {
|
||||
const u32 v = m_intermediate_hash[i];
|
||||
|
||||
dst[sizeof(u32) * i + 3] = static_cast<u8>(v >> (BITSIZEOF(u8) * 0));
|
||||
dst[sizeof(u32) * i + 2] = static_cast<u8>(v >> (BITSIZEOF(u8) * 1));
|
||||
dst[sizeof(u32) * i + 1] = static_cast<u8>(v >> (BITSIZEOF(u8) * 2));
|
||||
dst[sizeof(u32) * i + 0] = static_cast<u8>(v >> (BITSIZEOF(u8) * 3));
|
||||
}
|
||||
}
|
||||
|
||||
constexpr size_t GetBufferedDataSize() const { return m_buffered_bytes; }
|
||||
|
||||
constexpr void GetBufferedData(u8 *dst, size_t dst_size) const {
|
||||
AMS_ASSERT(dst_size >= this->GetBufferedDataSize());
|
||||
AMS_UNUSED(dst_size);
|
||||
|
||||
for (size_t i = 0; i < m_buffered_bytes; ++i) {
|
||||
dst[i] = m_buffer[i];
|
||||
}
|
||||
}
|
||||
private:
|
||||
static constexpr ALWAYS_INLINE u32 Choose(u32 x, u32 y, u32 z) {
|
||||
return (x & y) ^ ((~x) & z);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE u32 Majority(u32 x, u32 y, u32 z) {
|
||||
return (x & y) ^ (x & z) ^ (y & z);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE u32 LargeSigma0(u32 x) {
|
||||
return util::RotateRight<u32>(x, 2) ^ util::RotateRight<u32>(x, 13) ^ util::RotateRight<u32>(x, 22);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE u32 LargeSigma1(u32 x) {
|
||||
return util::RotateRight<u32>(x, 6) ^ util::RotateRight<u32>(x, 11) ^ util::RotateRight<u32>(x, 25);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE u32 SmallSigma0(u32 x) {
|
||||
return util::RotateRight<u32>(x, 7) ^ util::RotateRight<u32>(x, 18) ^ (x >> 3);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE u32 SmallSigma1(u32 x) {
|
||||
return util::RotateRight<u32>(x, 17) ^ util::RotateRight<u32>(x, 19) ^ (x >> 10);
|
||||
}
|
||||
|
||||
constexpr void ProcessBlock(const u8 *data) {
|
||||
/* Load work variables. */
|
||||
u32 a = m_intermediate_hash[0];
|
||||
u32 b = m_intermediate_hash[1];
|
||||
u32 c = m_intermediate_hash[2];
|
||||
u32 d = m_intermediate_hash[3];
|
||||
u32 e = m_intermediate_hash[4];
|
||||
u32 f = m_intermediate_hash[5];
|
||||
u32 g = m_intermediate_hash[6];
|
||||
u32 h = m_intermediate_hash[7];
|
||||
u32 tmp[2]{};
|
||||
size_t i = 0;
|
||||
|
||||
/* Copy the input. */
|
||||
u32 w[64]{};
|
||||
for (size_t i = 0; i < BlockSize / sizeof(u32); ++i) {
|
||||
u32 v = 0;
|
||||
v |= static_cast<u32>(data[sizeof(u32) * i + 0]) << (BITSIZEOF(u8) * 3);
|
||||
v |= static_cast<u32>(data[sizeof(u32) * i + 1]) << (BITSIZEOF(u8) * 2);
|
||||
v |= static_cast<u32>(data[sizeof(u32) * i + 2]) << (BITSIZEOF(u8) * 1);
|
||||
v |= static_cast<u32>(data[sizeof(u32) * i + 3]) << (BITSIZEOF(u8) * 0);
|
||||
|
||||
w[i] = v;
|
||||
}
|
||||
|
||||
/* Initialize the rest of w. */
|
||||
for (i = BlockSize / sizeof(u32); i < util::size(w); ++i) {
|
||||
const u32 *prev = w + (i - BlockSize / sizeof(u32));
|
||||
w[i] = prev[0] + SmallSigma0(prev[1]) + prev[9] + SmallSigma1(prev[14]);
|
||||
}
|
||||
|
||||
/* Perform rounds. */
|
||||
{
|
||||
const u32 RoundConstants[0x40] = {
|
||||
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
|
||||
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
|
||||
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
|
||||
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
|
||||
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
|
||||
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
|
||||
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
|
||||
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
|
||||
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
|
||||
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
|
||||
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
|
||||
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
|
||||
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
|
||||
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
|
||||
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
|
||||
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
|
||||
};
|
||||
|
||||
for (i = 0; i < 64; ++i) {
|
||||
tmp[0] = h + LargeSigma1(e) + Choose(e, f, g) + RoundConstants[i] + w[i];
|
||||
tmp[1] = LargeSigma0(a) + Majority(a, b, c);
|
||||
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + tmp[0];
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = tmp[0] + tmp[1];
|
||||
}
|
||||
}
|
||||
|
||||
/* Update intermediate hash. */
|
||||
m_intermediate_hash[0] += a;
|
||||
m_intermediate_hash[1] += b;
|
||||
m_intermediate_hash[2] += c;
|
||||
m_intermediate_hash[3] += d;
|
||||
m_intermediate_hash[4] += e;
|
||||
m_intermediate_hash[5] += f;
|
||||
m_intermediate_hash[6] += g;
|
||||
m_intermediate_hash[7] += h;
|
||||
}
|
||||
|
||||
constexpr void ProcessLastBlock() {
|
||||
/* Setup the final block. */
|
||||
constexpr const auto BlockSizeWithoutSizeField = BlockSize - sizeof(u64);
|
||||
|
||||
/* Increment our bits consumed. */
|
||||
m_bits_consumed += BITSIZEOF(u8) * m_buffered_bytes;
|
||||
|
||||
/* Add 0x80 terminator. */
|
||||
m_buffer[m_buffered_bytes++] = 0x80;
|
||||
|
||||
/* If we can process the size field directly, do so, otherwise set up to process it. */
|
||||
if (m_buffered_bytes <= BlockSizeWithoutSizeField) {
|
||||
/* Clear up to size field. */
|
||||
for (size_t i = 0; i < BlockSizeWithoutSizeField - m_buffered_bytes; ++i) {
|
||||
m_buffer[m_buffered_bytes + i] = 0;
|
||||
}
|
||||
} else {
|
||||
/* Consume full block */
|
||||
for (size_t i = 0; i < BlockSize - m_buffered_bytes; ++i) {
|
||||
m_buffer[m_buffered_bytes + i] = 0;
|
||||
}
|
||||
|
||||
this->ProcessBlock(m_buffer);
|
||||
|
||||
/* Clear up to size field. */
|
||||
for (size_t i = 0; i < BlockSizeWithoutSizeField; ++i) {
|
||||
m_buffer[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the size field. */
|
||||
m_buffer[BlockSizeWithoutSizeField + 0] = static_cast<u8>((m_bits_consumed >> (BITSIZEOF(u8) * 7)) & 0xFF);
|
||||
m_buffer[BlockSizeWithoutSizeField + 1] = static_cast<u8>((m_bits_consumed >> (BITSIZEOF(u8) * 6)) & 0xFF);
|
||||
m_buffer[BlockSizeWithoutSizeField + 2] = static_cast<u8>((m_bits_consumed >> (BITSIZEOF(u8) * 5)) & 0xFF);
|
||||
m_buffer[BlockSizeWithoutSizeField + 3] = static_cast<u8>((m_bits_consumed >> (BITSIZEOF(u8) * 4)) & 0xFF);
|
||||
m_buffer[BlockSizeWithoutSizeField + 4] = static_cast<u8>((m_bits_consumed >> (BITSIZEOF(u8) * 3)) & 0xFF);
|
||||
m_buffer[BlockSizeWithoutSizeField + 5] = static_cast<u8>((m_bits_consumed >> (BITSIZEOF(u8) * 2)) & 0xFF);
|
||||
m_buffer[BlockSizeWithoutSizeField + 6] = static_cast<u8>((m_bits_consumed >> (BITSIZEOF(u8) * 1)) & 0xFF);
|
||||
m_buffer[BlockSizeWithoutSizeField + 7] = static_cast<u8>((m_bits_consumed >> (BITSIZEOF(u8) * 0)) & 0xFF);
|
||||
|
||||
/* Process the final block. */
|
||||
this->ProcessBlock(m_buffer);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/impl/crypto_hash_function.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
struct Sha3Context;
|
||||
|
||||
}
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
template<size_t _HashSize>
|
||||
class Sha3Impl {
|
||||
public:
|
||||
static constexpr size_t InternalStateSize = 200;
|
||||
static constexpr size_t HashSize = _HashSize;
|
||||
static constexpr size_t BlockSize = InternalStateSize - 2 * HashSize;
|
||||
private:
|
||||
enum State {
|
||||
State_None,
|
||||
State_Initialized,
|
||||
State_Done,
|
||||
};
|
||||
private:
|
||||
u64 m_internal_state[InternalStateSize / sizeof(u64)];
|
||||
size_t m_buffered_bytes;
|
||||
State m_state;
|
||||
public:
|
||||
Sha3Impl() : m_state(State_None) { /* ... */ }
|
||||
~Sha3Impl() {
|
||||
ClearMemory(this, sizeof(*this));
|
||||
}
|
||||
|
||||
void Initialize();
|
||||
void Update(const void *data, size_t size);
|
||||
void GetHash(void *dst, size_t size);
|
||||
|
||||
void InitializeWithContext(const Sha3Context *context);
|
||||
void GetContext(Sha3Context *context) const;
|
||||
private:
|
||||
void ProcessBlock();
|
||||
void ProcessLastBlock();
|
||||
};
|
||||
|
||||
static_assert(HashFunction<Sha3Impl<224 / BITSIZEOF(u8)>>);
|
||||
static_assert(HashFunction<Sha3Impl<256 / BITSIZEOF(u8)>>);
|
||||
static_assert(HashFunction<Sha3Impl<384 / BITSIZEOF(u8)>>);
|
||||
static_assert(HashFunction<Sha3Impl<512 / BITSIZEOF(u8)>>);
|
||||
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util.hpp>
|
||||
#include <vapours/crypto/crypto_memory_clear.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
|
||||
namespace ams::crypto::impl {
|
||||
|
||||
class XtsModeImpl {
|
||||
NON_COPYABLE(XtsModeImpl);
|
||||
NON_MOVEABLE(XtsModeImpl);
|
||||
public:
|
||||
/* TODO: More generic support. */
|
||||
static constexpr size_t BlockSize = 16;
|
||||
static constexpr size_t IvSize = 16;
|
||||
private:
|
||||
enum State {
|
||||
State_None,
|
||||
State_Initialized,
|
||||
State_Processing,
|
||||
State_Done
|
||||
};
|
||||
private:
|
||||
u8 m_buffer[BlockSize];
|
||||
u8 m_tweak[BlockSize];
|
||||
u8 m_last_block[BlockSize];
|
||||
size_t m_num_buffered;
|
||||
const void *m_cipher_ctx;
|
||||
void (*m_cipher_func)(void *dst_block, const void *src_block, const void *cipher_ctx);
|
||||
State m_state;
|
||||
public:
|
||||
XtsModeImpl() : m_num_buffered(0), m_state(State_None) { /* ... */ }
|
||||
|
||||
~XtsModeImpl() {
|
||||
ClearMemory(this, sizeof(*this));
|
||||
}
|
||||
private:
|
||||
template<typename BlockCipher>
|
||||
static void EncryptBlockCallback(void *dst_block, const void *src_block, const void *cipher) {
|
||||
return static_cast<const BlockCipher *>(cipher)->EncryptBlock(dst_block, BlockCipher::BlockSize, src_block, BlockCipher::BlockSize);
|
||||
}
|
||||
|
||||
template<typename BlockCipher>
|
||||
static void DecryptBlockCallback(void *dst_block, const void *src_block, const void *cipher) {
|
||||
return static_cast<const BlockCipher *>(cipher)->DecryptBlock(dst_block, BlockCipher::BlockSize, src_block, BlockCipher::BlockSize);
|
||||
}
|
||||
|
||||
template<typename BlockCipher>
|
||||
void Initialize(const BlockCipher *cipher, const void *tweak, size_t tweak_size) {
|
||||
AMS_ASSERT(tweak_size == IvSize);
|
||||
AMS_UNUSED(tweak_size);
|
||||
|
||||
cipher->EncryptBlock(m_tweak, IvSize, tweak, IvSize);
|
||||
|
||||
m_num_buffered = 0;
|
||||
m_state = State_Initialized;
|
||||
}
|
||||
|
||||
void ProcessBlock(u8 *dst, const u8 *src);
|
||||
public:
|
||||
template<typename BlockCipher1, typename BlockCipher2>
|
||||
void InitializeEncryption(const BlockCipher1 *cipher1, const BlockCipher2 *cipher2, const void *tweak, size_t tweak_size) {
|
||||
static_assert(BlockCipher1::BlockSize == BlockSize);
|
||||
static_assert(BlockCipher2::BlockSize == BlockSize);
|
||||
|
||||
m_cipher_ctx = cipher1;
|
||||
m_cipher_func = EncryptBlockCallback<BlockCipher1>;
|
||||
|
||||
this->Initialize(cipher2, tweak, tweak_size);
|
||||
}
|
||||
|
||||
template<typename BlockCipher1, typename BlockCipher2>
|
||||
void InitializeDecryption(const BlockCipher1 *cipher1, const BlockCipher2 *cipher2, const void *tweak, size_t tweak_size) {
|
||||
static_assert(BlockCipher1::BlockSize == BlockSize);
|
||||
static_assert(BlockCipher2::BlockSize == BlockSize);
|
||||
|
||||
m_cipher_ctx = cipher1;
|
||||
m_cipher_func = DecryptBlockCallback<BlockCipher1>;
|
||||
|
||||
this->Initialize(cipher2, tweak, tweak_size);
|
||||
}
|
||||
|
||||
template<typename BlockCipher>
|
||||
size_t Update(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
return this->UpdateGeneric(dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
template<typename BlockCipher>
|
||||
size_t ProcessBlocks(u8 *dst, const u8 *src, size_t num_blocks) {
|
||||
return this->ProcessBlocksGeneric(dst, src, num_blocks);
|
||||
}
|
||||
|
||||
size_t GetBufferedDataSize() const {
|
||||
return m_num_buffered;
|
||||
}
|
||||
|
||||
constexpr size_t GetBlockSize() const {
|
||||
return BlockSize;
|
||||
}
|
||||
|
||||
size_t FinalizeEncryption(void *dst, size_t dst_size);
|
||||
size_t FinalizeDecryption(void *dst, size_t dst_size);
|
||||
|
||||
size_t UpdateGeneric(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
size_t ProcessBlocksGeneric(u8 *dst, const u8 *src, size_t num_blocks);
|
||||
|
||||
size_t ProcessPartialData(u8 *dst, const u8 *src, size_t size);
|
||||
size_t ProcessRemainingData(u8 *dst, const u8 *src, size_t size);
|
||||
};
|
||||
|
||||
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||
template<> size_t XtsModeImpl::Update<AesEncryptor128>(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
template<> size_t XtsModeImpl::Update<AesEncryptor192>(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
template<> size_t XtsModeImpl::Update<AesEncryptor256>(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
|
||||
template<> size_t XtsModeImpl::Update<AesDecryptor128>(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
template<> size_t XtsModeImpl::Update<AesDecryptor192>(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
template<> size_t XtsModeImpl::Update<AesDecryptor256>(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
#endif
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user