mirror of
https://github.com/jakcron/nstool
synced 2024-11-14 17:56:39 +00:00
[nstool|es] Add cert validation.
This commit is contained in:
parent
6f5c7fd353
commit
0aebf43f4b
9 changed files with 184 additions and 61 deletions
14
lib/libes/include/es/SignUtils.h
Normal file
14
lib/libes/include/es/SignUtils.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
#include <es/sign.h>
|
||||
#include <crypto/sha.h>
|
||||
|
||||
namespace es
|
||||
{
|
||||
|
||||
namespace sign
|
||||
{
|
||||
es::sign::SignatureAlgo getSignatureAlgo(es::sign::SignatureId sign_id);
|
||||
es::sign::HashAlgo getHashAlgo(es::sign::SignatureId sign_id);
|
||||
}
|
||||
|
||||
}
|
|
@ -24,8 +24,8 @@ namespace es
|
|||
// variables
|
||||
void clear();
|
||||
|
||||
es::sign::SignType getSignType() const;
|
||||
void setSignType(es::sign::SignType type);
|
||||
es::sign::SignatureId getSignType() const;
|
||||
void setSignType(es::sign::SignatureId type);
|
||||
|
||||
bool isLittleEndian() const;
|
||||
void setLittleEndian(bool isLE);
|
||||
|
@ -41,7 +41,7 @@ namespace es
|
|||
fnd::Vec<byte_t> mRawBinary;
|
||||
|
||||
// variables
|
||||
es::sign::SignType mSignType;
|
||||
es::sign::SignatureId mSignType;
|
||||
bool mIsLittleEndian;
|
||||
fnd::Vec<byte_t> mSignature;
|
||||
};
|
||||
|
|
|
@ -9,14 +9,27 @@ namespace es
|
|||
{
|
||||
namespace sign
|
||||
{
|
||||
enum SignType
|
||||
enum SignatureId
|
||||
{
|
||||
SIGN_RSA4096_SHA1 = 0x10000,
|
||||
SIGN_RSA2048_SHA1,
|
||||
SIGN_ECDSA240_SHA1,
|
||||
SIGN_RSA4096_SHA256,
|
||||
SIGN_RSA2048_SHA256,
|
||||
SIGN_ECDSA240_SHA256,
|
||||
SIGN_ID_RSA4096_SHA1 = 0x10000,
|
||||
SIGN_ID_RSA2048_SHA1,
|
||||
SIGN_ID_ECDSA240_SHA1,
|
||||
SIGN_ID_RSA4096_SHA256,
|
||||
SIGN_ID_RSA2048_SHA256,
|
||||
SIGN_ID_ECDSA240_SHA256,
|
||||
};
|
||||
|
||||
enum SignatureAlgo
|
||||
{
|
||||
SIGN_ALGO_RSA4096,
|
||||
SIGN_ALGO_RSA2048,
|
||||
SIGN_ALGO_ECDSA240
|
||||
};
|
||||
|
||||
enum HashAlgo
|
||||
{
|
||||
HASH_ALGO_SHA1,
|
||||
HASH_ALGO_SHA256
|
||||
};
|
||||
|
||||
static const size_t kEcdsaSigSize = 0x3C;
|
||||
|
|
45
lib/libes/source/SignUtils.cpp
Normal file
45
lib/libes/source/SignUtils.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#include <es/SignUtils.h>
|
||||
|
||||
es::sign::SignatureAlgo es::sign::getSignatureAlgo(es::sign::SignatureId sign_id)
|
||||
{
|
||||
SignatureAlgo sign_algo = SIGN_ALGO_RSA4096;
|
||||
|
||||
switch (sign_id)
|
||||
{
|
||||
case (es::sign::SIGN_ID_RSA4096_SHA1):
|
||||
case (es::sign::SIGN_ID_RSA4096_SHA256):
|
||||
sign_algo = SIGN_ALGO_RSA4096;
|
||||
break;
|
||||
case (es::sign::SIGN_ID_RSA2048_SHA1):
|
||||
case (es::sign::SIGN_ID_RSA2048_SHA256):
|
||||
sign_algo = SIGN_ALGO_RSA2048;
|
||||
break;
|
||||
case (es::sign::SIGN_ID_ECDSA240_SHA1):
|
||||
case (es::sign::SIGN_ID_ECDSA240_SHA256):
|
||||
sign_algo = SIGN_ALGO_ECDSA240;
|
||||
break;
|
||||
};
|
||||
|
||||
return sign_algo;
|
||||
}
|
||||
|
||||
es::sign::HashAlgo es::sign::getHashAlgo(es::sign::SignatureId sign_id)
|
||||
{
|
||||
HashAlgo hash_algo = HASH_ALGO_SHA1;
|
||||
|
||||
switch (sign_id)
|
||||
{
|
||||
case (es::sign::SIGN_ID_RSA4096_SHA1):
|
||||
case (es::sign::SIGN_ID_RSA2048_SHA1):
|
||||
case (es::sign::SIGN_ID_ECDSA240_SHA1):
|
||||
hash_algo = HASH_ALGO_SHA1;
|
||||
break;
|
||||
case (es::sign::SIGN_ID_RSA4096_SHA256):
|
||||
case (es::sign::SIGN_ID_RSA2048_SHA256):
|
||||
case (es::sign::SIGN_ID_ECDSA240_SHA256):
|
||||
hash_algo = HASH_ALGO_SHA256;
|
||||
break;
|
||||
};
|
||||
|
||||
return hash_algo;
|
||||
}
|
|
@ -37,18 +37,18 @@ void es::SignatureBlock::toBytes()
|
|||
|
||||
switch (mSignType)
|
||||
{
|
||||
case (sign::SIGN_RSA4096_SHA1):
|
||||
case (sign::SIGN_RSA4096_SHA256):
|
||||
case (sign::SIGN_ID_RSA4096_SHA1):
|
||||
case (sign::SIGN_ID_RSA4096_SHA256):
|
||||
totalSize = sizeof(sRsa4096SignBlock);
|
||||
sigSize = crypto::rsa::kRsa4096Size;
|
||||
break;
|
||||
case (sign::SIGN_RSA2048_SHA1):
|
||||
case (sign::SIGN_RSA2048_SHA256):
|
||||
case (sign::SIGN_ID_RSA2048_SHA1):
|
||||
case (sign::SIGN_ID_RSA2048_SHA256):
|
||||
totalSize = sizeof(sRsa2048SignBlock);
|
||||
sigSize = crypto::rsa::kRsa2048Size;
|
||||
break;
|
||||
case (sign::SIGN_ECDSA240_SHA1):
|
||||
case (sign::SIGN_ECDSA240_SHA256):
|
||||
case (sign::SIGN_ID_ECDSA240_SHA1):
|
||||
case (sign::SIGN_ID_ECDSA240_SHA256):
|
||||
totalSize = sizeof(sEcdsa240SignBlock);
|
||||
sigSize = sign::kEcdsaSigSize;
|
||||
break;
|
||||
|
@ -80,18 +80,18 @@ void es::SignatureBlock::fromBytes(const byte_t* src, size_t size)
|
|||
signType = ((be_uint32_t*)src)->get();
|
||||
switch (signType)
|
||||
{
|
||||
case (sign::SIGN_RSA4096_SHA1):
|
||||
case (sign::SIGN_RSA4096_SHA256):
|
||||
case (sign::SIGN_ID_RSA4096_SHA1):
|
||||
case (sign::SIGN_ID_RSA4096_SHA256):
|
||||
totalSize = sizeof(sRsa4096SignBlock);
|
||||
sigSize = crypto::rsa::kRsa4096Size;
|
||||
break;
|
||||
case (sign::SIGN_RSA2048_SHA1):
|
||||
case (sign::SIGN_RSA2048_SHA256):
|
||||
case (sign::SIGN_ID_RSA2048_SHA1):
|
||||
case (sign::SIGN_ID_RSA2048_SHA256):
|
||||
totalSize = sizeof(sRsa2048SignBlock);
|
||||
sigSize = crypto::rsa::kRsa2048Size;
|
||||
break;
|
||||
case (sign::SIGN_ECDSA240_SHA1):
|
||||
case (sign::SIGN_ECDSA240_SHA256):
|
||||
case (sign::SIGN_ID_ECDSA240_SHA1):
|
||||
case (sign::SIGN_ID_ECDSA240_SHA256):
|
||||
totalSize = sizeof(sEcdsa240SignBlock);
|
||||
sigSize = sign::kEcdsaSigSize;
|
||||
break;
|
||||
|
@ -103,18 +103,18 @@ void es::SignatureBlock::fromBytes(const byte_t* src, size_t size)
|
|||
signType = ((le_uint32_t*)src)->get();
|
||||
switch (signType)
|
||||
{
|
||||
case (sign::SIGN_RSA4096_SHA1):
|
||||
case (sign::SIGN_RSA4096_SHA256):
|
||||
case (sign::SIGN_ID_RSA4096_SHA1):
|
||||
case (sign::SIGN_ID_RSA4096_SHA256):
|
||||
totalSize = sizeof(sRsa4096SignBlock);
|
||||
sigSize = crypto::rsa::kRsa4096Size;
|
||||
break;
|
||||
case (sign::SIGN_RSA2048_SHA1):
|
||||
case (sign::SIGN_RSA2048_SHA256):
|
||||
case (sign::SIGN_ID_RSA2048_SHA1):
|
||||
case (sign::SIGN_ID_RSA2048_SHA256):
|
||||
totalSize = sizeof(sRsa2048SignBlock);
|
||||
sigSize = crypto::rsa::kRsa2048Size;
|
||||
break;
|
||||
case (sign::SIGN_ECDSA240_SHA1):
|
||||
case (sign::SIGN_ECDSA240_SHA256):
|
||||
case (sign::SIGN_ID_ECDSA240_SHA1):
|
||||
case (sign::SIGN_ID_ECDSA240_SHA256):
|
||||
totalSize = sizeof(sEcdsa240SignBlock);
|
||||
sigSize = sign::kEcdsaSigSize;
|
||||
break;
|
||||
|
@ -133,7 +133,7 @@ void es::SignatureBlock::fromBytes(const byte_t* src, size_t size)
|
|||
mRawBinary.alloc(totalSize);
|
||||
memcpy(mRawBinary.data(), src, totalSize);
|
||||
|
||||
mSignType = (sign::SignType)signType;
|
||||
mSignType = (sign::SignatureId)signType;
|
||||
mSignature.alloc(sigSize);
|
||||
memcpy(mSignature.data(), mRawBinary.data() + 4, sigSize);
|
||||
}
|
||||
|
@ -146,17 +146,17 @@ const fnd::Vec<byte_t>& es::SignatureBlock::getBytes() const
|
|||
void es::SignatureBlock::clear()
|
||||
{
|
||||
mRawBinary.clear();
|
||||
mSignType = sign::SIGN_RSA4096_SHA1;
|
||||
mSignType = sign::SIGN_ID_RSA4096_SHA1;
|
||||
mIsLittleEndian = false;
|
||||
mSignature.clear();
|
||||
}
|
||||
|
||||
es::sign::SignType es::SignatureBlock::getSignType() const
|
||||
es::sign::SignatureId es::SignatureBlock::getSignType() const
|
||||
{
|
||||
return mSignType;
|
||||
}
|
||||
|
||||
void es::SignatureBlock::setSignType(es::sign::SignType type)
|
||||
void es::SignatureBlock::setSignType(es::sign::SignatureId type)
|
||||
{
|
||||
mSignType = type;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <iomanip>
|
||||
|
||||
#include <fnd/SimpleTextOutput.h>
|
||||
#include <es/SignUtils.h>
|
||||
#include "OffsetAdjustedIFile.h"
|
||||
#include "EsCertProcess.h"
|
||||
|
||||
|
@ -83,25 +84,50 @@ void EsCertProcess::validateCerts()
|
|||
void EsCertProcess::validateCert(const es::SignedData<es::CertificateBody>& cert)
|
||||
{
|
||||
std::string cert_ident = cert.getBody().getIssuer() + es::sign::kIdentDelimiter + cert.getBody().getSubject();
|
||||
|
||||
es::sign::SignatureAlgo cert_sign_algo = es::sign::getSignatureAlgo(cert.getSignature().getSignType());
|
||||
es::sign::HashAlgo cert_hash_algo = es::sign::getHashAlgo(cert.getSignature().getSignType());
|
||||
byte_t cert_hash[crypto::sha::kSha256HashLen];
|
||||
memset(cert_hash, 0, crypto::sha::kSha256HashLen);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
// special case if signed by Root
|
||||
if (cert.getBody().getIssuer() == es::sign::kRootIssuerStr)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "Signed by Root");
|
||||
}
|
||||
|
||||
const es::CertificateBody& issuer = getIssuerCert(cert.getBody().getIssuer()).getBody();
|
||||
// get cert hash
|
||||
switch (cert_hash_algo)
|
||||
{
|
||||
case (es::sign::HASH_ALGO_SHA1):
|
||||
crypto::sha::Sha1(cert.getBody().getBytes().data(), cert.getBody().getBytes().size(), cert_hash);
|
||||
break;
|
||||
case (es::sign::HASH_ALGO_SHA256):
|
||||
crypto::sha::Sha256(cert.getBody().getBytes().data(), cert.getBody().getBytes().size(), cert_hash);
|
||||
break;
|
||||
default:
|
||||
throw fnd::Exception(kModuleName, "Unrecognised hash type");
|
||||
}
|
||||
|
||||
if (issuer.getPublicKeyType() == es::cert::RSA4096 && (cert.getSignature().getSignType() == es::sign::SIGN_RSA4096_SHA1 || cert.getSignature().getSignType() == es::sign::SIGN_RSA4096_SHA256))
|
||||
// try to find issuer cert
|
||||
const es::CertificateBody& issuer = getIssuerCert(cert.getBody().getIssuer()).getBody();
|
||||
es::cert::PublicKeyType issuer_pubk_type = issuer.getPublicKeyType();
|
||||
|
||||
// validate signature
|
||||
int sig_validate_res = -1;
|
||||
|
||||
if (issuer_pubk_type == es::cert::RSA4096 && cert_sign_algo == es::sign::SIGN_ALGO_RSA4096)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "RSA4096 signatures are not supported");
|
||||
sig_validate_res = crypto::rsa::pkcs::rsaVerify(issuer.getRsa4098PublicKey(), getCryptoHashAlgoFromEsSignHashAlgo(cert_hash_algo), cert_hash, cert.getSignature().getSignature().data());
|
||||
}
|
||||
else if (issuer.getPublicKeyType() == es::cert::RSA2048 && (cert.getSignature().getSignType() == es::sign::SIGN_RSA2048_SHA1 || cert.getSignature().getSignType() == es::sign::SIGN_RSA2048_SHA256))
|
||||
else if (issuer_pubk_type == es::cert::RSA2048 && cert_sign_algo == es::sign::SIGN_ALGO_RSA2048)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "RSA2048 signatures are not supported");
|
||||
sig_validate_res = crypto::rsa::pkcs::rsaVerify(issuer.getRsa2048PublicKey(), getCryptoHashAlgoFromEsSignHashAlgo(cert_hash_algo), cert_hash, cert.getSignature().getSignature().data());
|
||||
}
|
||||
else if (issuer.getPublicKeyType() == es::cert::ECDSA240 && (cert.getSignature().getSignType() == es::sign::SIGN_ECDSA240_SHA1 || cert.getSignature().getSignType() == es::sign::SIGN_ECDSA240_SHA256))
|
||||
else if (issuer_pubk_type == es::cert::ECDSA240 && cert_sign_algo == es::sign::SIGN_ALGO_ECDSA240)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "ECDSA signatures are not supported");
|
||||
}
|
||||
|
@ -109,10 +135,15 @@ void EsCertProcess::validateCert(const es::SignedData<es::CertificateBody>& cert
|
|||
{
|
||||
throw fnd::Exception(kModuleName, "Mismatch between issuer public key and signature type");
|
||||
}
|
||||
|
||||
if (sig_validate_res != 0)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "Incorrect signature");
|
||||
}
|
||||
}
|
||||
catch (const fnd::Exception& e)
|
||||
{
|
||||
printf("[WARNING] Failed to validate %s (%s)\n", cert_ident.c_str(), e.error());
|
||||
std::cout << "[WARNING] Failed to validate " << cert_ident << " (" << e.error() << ")" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -194,27 +225,45 @@ const es::SignedData<es::CertificateBody>& EsCertProcess::getIssuerCert(const st
|
|||
throw fnd::Exception(kModuleName, "Issuer certificate does not exist");
|
||||
}
|
||||
|
||||
const char* EsCertProcess::getSignTypeStr(es::sign::SignType type) const
|
||||
crypto::sha::HashType EsCertProcess::getCryptoHashAlgoFromEsSignHashAlgo(es::sign::HashAlgo es_hash_algo) const
|
||||
{
|
||||
crypto::sha::HashType hash_type = crypto::sha::HASH_SHA1;
|
||||
|
||||
switch (es_hash_algo)
|
||||
{
|
||||
case (es::sign::HASH_ALGO_SHA1):
|
||||
hash_type = crypto::sha::HASH_SHA1;
|
||||
break;
|
||||
case (es::sign::HASH_ALGO_SHA256):
|
||||
hash_type = crypto::sha::HASH_SHA256;
|
||||
break;
|
||||
};
|
||||
|
||||
return hash_type;
|
||||
}
|
||||
|
||||
|
||||
const char* EsCertProcess::getSignTypeStr(es::sign::SignatureId type) const
|
||||
{
|
||||
const char* str;
|
||||
switch (type)
|
||||
{
|
||||
case (es::sign::SIGN_RSA4096_SHA1):
|
||||
case (es::sign::SIGN_ID_RSA4096_SHA1):
|
||||
str = "RSA4096-SHA1";
|
||||
break;
|
||||
case (es::sign::SIGN_RSA2048_SHA1):
|
||||
case (es::sign::SIGN_ID_RSA2048_SHA1):
|
||||
str = "RSA2048-SHA1";
|
||||
break;
|
||||
case (es::sign::SIGN_ECDSA240_SHA1):
|
||||
case (es::sign::SIGN_ID_ECDSA240_SHA1):
|
||||
str = "ECDSA240-SHA1";
|
||||
break;
|
||||
case (es::sign::SIGN_RSA4096_SHA256):
|
||||
case (es::sign::SIGN_ID_RSA4096_SHA256):
|
||||
str = "RSA4096-SHA256";
|
||||
break;
|
||||
case (es::sign::SIGN_RSA2048_SHA256):
|
||||
case (es::sign::SIGN_ID_RSA2048_SHA256):
|
||||
str = "RSA2048-SHA256";
|
||||
break;
|
||||
case (es::sign::SIGN_ECDSA240_SHA256):
|
||||
case (es::sign::SIGN_ID_ECDSA240_SHA256):
|
||||
str = "ECDSA240-SHA256";
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -40,7 +40,9 @@ private:
|
|||
|
||||
const es::SignedData<es::CertificateBody>& getIssuerCert(const std::string& issuer_name) const;
|
||||
|
||||
const char* getSignTypeStr(es::sign::SignType type) const;
|
||||
crypto::sha::HashType getCryptoHashAlgoFromEsSignHashAlgo(es::sign::HashAlgo hash_algo) const;
|
||||
|
||||
const char* getSignTypeStr(es::sign::SignatureId type) const;
|
||||
const char* getEndiannessStr(bool isLittleEndian) const;
|
||||
const char* getPublicKeyTypeStr(es::cert::PublicKeyType type) const;
|
||||
};
|
|
@ -132,23 +132,23 @@ const char* EsTikProcess::getSignTypeStr(uint32_t type) const
|
|||
const char* str = nullptr;
|
||||
switch(type)
|
||||
{
|
||||
case (es::sign::SIGN_RSA4096_SHA1):
|
||||
str = "RSA4096_SHA1";
|
||||
case (es::sign::SIGN_ID_RSA4096_SHA1):
|
||||
str = "RSA4096-SHA1";
|
||||
break;
|
||||
case (es::sign::SIGN_RSA2048_SHA1):
|
||||
str = "RSA2048_SHA1";
|
||||
case (es::sign::SIGN_ID_RSA2048_SHA1):
|
||||
str = "RSA2048-SHA1";
|
||||
break;
|
||||
case (es::sign::SIGN_ECDSA240_SHA1):
|
||||
str = "ECDSA240_SHA1";
|
||||
case (es::sign::SIGN_ID_ECDSA240_SHA1):
|
||||
str = "ECDSA240-SHA1";
|
||||
break;
|
||||
case (es::sign::SIGN_RSA4096_SHA256):
|
||||
str = "RSA4096_SHA256";
|
||||
case (es::sign::SIGN_ID_RSA4096_SHA256):
|
||||
str = "RSA4096-SHA256";
|
||||
break;
|
||||
case (es::sign::SIGN_RSA2048_SHA256):
|
||||
str = "RSA2048_SHA256";
|
||||
case (es::sign::SIGN_ID_RSA2048_SHA256):
|
||||
str = "RSA2048-SHA256";
|
||||
break;
|
||||
case (es::sign::SIGN_ECDSA240_SHA256):
|
||||
str = "ECDSA240_SHA256";
|
||||
case (es::sign::SIGN_ID_ECDSA240_SHA256):
|
||||
str = "ECDSA240-SHA256";
|
||||
break;
|
||||
default:
|
||||
str = "Unknown";
|
||||
|
|
|
@ -882,7 +882,7 @@ bool UserSettings::determineValidEsCertFromSample(const fnd::Vec<byte_t>& sample
|
|||
if (sign.isLittleEndian() == true)
|
||||
return false;
|
||||
|
||||
if (sign.getSignType() != es::sign::SIGN_RSA4096_SHA256 && sign.getSignType() != es::sign::SIGN_RSA2048_SHA256 && sign.getSignType() != es::sign::SIGN_ECDSA240_SHA256)
|
||||
if (sign.getSignType() != es::sign::SIGN_ID_RSA4096_SHA256 && sign.getSignType() != es::sign::SIGN_ID_RSA2048_SHA256 && sign.getSignType() != es::sign::SIGN_ID_ECDSA240_SHA256)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -904,7 +904,7 @@ bool UserSettings::determineValidEsTikFromSample(const fnd::Vec<byte_t>& sample)
|
|||
if (sign.isLittleEndian() == false)
|
||||
return false;
|
||||
|
||||
if (sign.getSignType() != es::sign::SIGN_RSA2048_SHA256)
|
||||
if (sign.getSignType() != es::sign::SIGN_ID_RSA2048_SHA256)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
Loading…
Reference in a new issue