Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"

This reverts commit 15b7df8ef1.
This commit is contained in:
souldbminersmwc
2025-11-09 16:14:52 -05:00
parent 22ec140738
commit 21a3f953d7
3804 changed files with 435 additions and 570162 deletions

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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>;
}

View File

@@ -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>;
}

View File

@@ -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>; */
}

View File

@@ -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;
}
}

View File

@@ -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();
}
};
}

View File

@@ -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();
}
};
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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));
}
};
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}
};
}

View File

@@ -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));
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}
};
}

View File

@@ -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>>);
}

View File

@@ -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);
}
};
}

View File

@@ -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>;
};
}

View File

@@ -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);
}

View File

@@ -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. */
}

View File

@@ -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];
}
}
};
}

View File

@@ -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);
}
}

View File

@@ -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
}

View File

@@ -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);
};
}

View File

@@ -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>;
};
}

View File

@@ -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);
}
}

View File

@@ -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>);
}

View File

@@ -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;
}
};
}

View File

@@ -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;
}
};
}

View File

@@ -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;
}
};
}

View File

@@ -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>);
}

View File

@@ -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>);
}

View File

@@ -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);
}
};
}

View File

@@ -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)>>);
}

View File

@@ -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
}