This repository was archived by the owner on Jun 5, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 223
Expand file tree
/
Copy pathCryptoInterface.cpp
More file actions
155 lines (120 loc) · 5.73 KB
/
CryptoInterface.cpp
File metadata and controls
155 lines (120 loc) · 5.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) Microsoft Corporation. All rights reserved.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "CryptoInterface.h"
#include "ConfigurationManager.h"
extern UINT8* g_ConfigBuffer;
extern int g_ConfigBufferLength;
CryptoState::CryptoState( UINT32 dataAddress, UINT32 dataLength, BYTE* sig, UINT32 sigLength, UINT32 sectorType ) :
#if defined(ARM_V1_2)
m_dataAddress( CPU_GetCachableAddress( dataAddress ) ),
#else
m_dataAddress( dataAddress ),
#endif
m_dataLength ( dataLength ),
m_sig ( sig ),
m_sigLength ( sigLength ),
m_sectorType ( sectorType ),
m_handle ( NULL ),
m_res ( CRYPTO_FAILURE )
{
}
CryptoState::~CryptoState()
{
::Crypto_AbortRSAOperation( &m_handle );
}
bool CryptoState::VerifySignature( UINT32 keyIndex )
{
RSAKey* key = NULL;
// global config pointer not in bootloader image
//---------------------------------------------
// IF THERE IS NO CONFIG SECTOR IN THE FLASH SECTOR TABLE, THEN WE DON'T HAVE KEYS,
// THEREFORE WE WILL NOT PERFORM SIGNATURE CHECKING.
//
if(g_PrimaryConfigManager.m_device == NULL)
return true;
switch(m_sectorType)
{
case BlockRange::BLOCKTYPE_DEPLOYMENT:
// backwards compatibility
if(g_PrimaryConfigManager.GetTinyBooterVersion() != ConfigurationSector::c_CurrentVersionTinyBooter)
return true;
// if there is no key then we do not need to check the signature for the deployment sectors ONLY
if(g_PrimaryConfigManager.CheckSignatureKeyEmpty( ConfigurationSector::c_DeployKeyDeployment ))
{
return true;
}
key = (RSAKey*)g_PrimaryConfigManager.GetDeploymentKeys( ConfigurationSector::c_DeployKeyDeployment );
break;
// We have to be carefull of how we update the config sector as it contains the signature keys for firmware updates.
// Unlike all other updates, the config data is written into RAM in the buffer g_ConfigBuffer. THis is necessary because
// we don't want to blow away the keys unless we know that the signature is OK.
//
// Also, if the keys are unchanged then we don't require signature verification. Besides the keys there is not really anything
// we need to protect in this sector.
case BlockRange::BLOCKTYPE_CONFIG:
{
ASSERT(g_ConfigBufferLength > 0);
ASSERT(g_ConfigBuffer != NULL);
if(g_ConfigBuffer == NULL || g_ConfigBufferLength <= 0)
return false;
// the g_ConfigBuffer contains the new configuration data
const ConfigurationSector* pNewCfg = (const ConfigurationSector*)g_ConfigBuffer;
bool fCanWrite = false;
bool fRet = false;
if(pNewCfg->Version.TinyBooter == ConfigurationSector::c_CurrentVersionTinyBooter)
{
// allow updates of old config - for backwards compatibility
if(g_PrimaryConfigManager.GetTinyBooterVersion() != ConfigurationSector::c_CurrentVersionTinyBooter)
{
fCanWrite = true;
}
else
{
bool key1Change = (!g_PrimaryConfigManager.VerifiySignatureKey(0, (BYTE *)&pNewCfg->DeploymentKeys[0]));
bool key2Change = (!g_PrimaryConfigManager.VerifiySignatureKey(1, (BYTE *)&pNewCfg->DeploymentKeys[1]));
bool key1Empty = g_PrimaryConfigManager.CheckSignatureKeyEmpty(0);
bool key2Empty = g_PrimaryConfigManager.CheckSignatureKeyEmpty(1);
// make sure there are no key changes (unelss the key was uninitialized)
if((key1Empty || !key1Change) &&
(key2Empty || !key2Change))
{
fCanWrite = true;
}
}
if(fCanWrite)
{
// write the configuration
g_PrimaryConfigManager.EraseWriteConfigBlock( (BYTE *) g_ConfigBuffer, g_ConfigBufferLength );
fRet = true;
}
}
// free RAM buffer
free(g_ConfigBuffer);
g_ConfigBuffer = NULL;
return fRet;
}
break;
default:
// backwards compatibility
if(g_PrimaryConfigManager.GetTinyBooterVersion() != ConfigurationSector::c_CurrentVersionTinyBooter)
return true;
// if there is no key then we do not need to check the signature for the deployment sectors ONLY
if (g_PrimaryConfigManager.CheckSignatureKeyEmpty( keyIndex ))
{
return true;
}
key = (RSAKey*)g_PrimaryConfigManager.GetDeploymentKeys( keyIndex );
break;
};
if(key == NULL)
{
return false;
}
m_res = ::Crypto_StartRSAOperationWithKey( RSA_VERIFYSIGNATURE, key, (BYTE*)m_dataAddress, m_dataLength, (BYTE*)m_sig, m_sigLength, &m_handle );
while(CRYPTO_CONTINUE == m_res)
{
m_res = ::Crypto_StepRSAOperation( &m_handle );
}
return m_res == CRYPTO_SUCCESS;
}