-
Notifications
You must be signed in to change notification settings - Fork 0
/
sec_sign.c
226 lines (185 loc) · 6.06 KB
/
sec_sign.c
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
#include "qcommon.h"
#include "sec_sign.h"
#include "sec_crypto.h"
#include "tomcrypt/math/tommath.h"
qboolean Sec_MakeRsaKey(int size,const rsa_key *key){
int res = rsa_make_key(NULL,0,size,65537,(rsa_key *)key);
return res;
}
qboolean Sec_SignHash(const char *in, size_t inSize, rsa_key *key, char *out, size_t *outSize){
long unsigned int is = inSize,os = *outSize;
int res = rsa_sign_hash_ex((const unsigned char *)in,is,(unsigned char *)out,&os,LTC_LTC_PKCS_1_V1_5,NULL,0,0,16,key);
*outSize = os;
return res;
}
qboolean Sec_VerifyHash(const char *sig, size_t sigSize, const rsa_key *key, const char *hash, int hashSize){
int n = 0;
int res = rsa_verify_hash_ex((const unsigned char *)sig,sigSize,(const unsigned char *)hash,hashSize,LTC_LTC_PKCS_1_V1_5,0,16,&n,(rsa_key *)key);
return (n == 1 && res == CRYPT_OK)? qtrue : qfalse;
}
qboolean Sec_MakeCertificate(rsa_key *key, const char *commonName, const char *companyName, int expires, const char *signature, int sigSize, sec_certificate_t *issuer,rsa_key *sigKey,sec_certificate_t *out){
hash_state md;
char hash[257];
size_t len;
const struct ltc_hash_descriptor *desc = &sha256_desc;
memset(out,0,sizeof(sec_certificate_t));
out->certificate.version = SEC_SIGN_VER;
strcpy(out->certificate.commonName,commonName);
strcpy(out->certificate.companyName,companyName);
out->certificate.dateExpires = expires;
out->certificate.dateIssued = time(NULL);
desc->init(&md);
desc->process(&md,(const unsigned char *)&(out->certificate),sizeof(sec_cert_t));
desc->done(&md,(unsigned char *)hash);
hash[256]=0;
out->certificate.pubKey.type = PK_PUBLIC;
mp_copy(out->certificate.pubKey.N,key->N);
mp_copy(out->certificate.pubKey.e,key->e);
len = sizeof(out->signature);
if(issuer != NULL){
if(!Sec_SignHash(hash,sizeof(hash),sigKey,out->signature,&len)){
return qfalse;
}
out->sigSize = len;
out->issuer = issuer;
}
return qtrue;
}
void Sec_ClearCertificate(sec_certificate_t *cert){
mp_clear_multi(cert->certificate.pubKey.N,cert->certificate.pubKey.e);
}
qboolean Sec_WriteCertificateToFile(sec_certificate_t *certificate, char *filename){
int len;
char buf[2048];
long unsigned int keysize;
sec_certificate_t *cert;
FILE *fp = fopen(filename,"w");
if(fp == NULL){
return qfalse;
}
fputs("IceOps Signature File. Visit us at www.iceops.in!",fp);
fputc(0,fp);
cert = certificate;
do{
len = 16 + strlen(cert->certificate.commonName) + strlen(cert->certificate.companyName) + cert->sigSize;
keysize = sizeof(buf);
if(rsa_export((unsigned char *)buf,&keysize,PK_PUBLIC,&(cert->certificate.pubKey)) != CRYPT_OK){
fclose(fp);
return qfalse;
}
len += keysize;
fprintf(fp,"%d\n",len);
fwrite(&cert->certificate,12,1,fp);
fputc(0,fp);
fputs(cert->certificate.commonName,fp);
fputs(cert->certificate.companyName,fp);
fprintf(fp,"%lu\n",keysize);
fwrite(buf,keysize,1,fp);
fprintf(fp,"%d\n",cert->sigSize);
fwrite(cert->signature,cert->sigSize,1,fp);
fputc(0,fp);
fputc(0,fp);
fflush(fp);
cert = cert->issuer;
}while(cert != NULL);
fclose(fp);
return qtrue;
}
qboolean Sec_ReadCertificateFromFile(sec_certificate_t *cert, char *filename){
return qtrue;
}
int Sec_Pem2Der(char* pemcert, int pemlen, unsigned char* dercert, unsigned int *derlen){
char* pos;
unsigned char assemblybuf[32768];
int i;
pos = strstr(pemcert, "--\n");
if(pos == NULL){
pos = strstr(pemcert, "--\r\n");
}
if(pos == NULL){
return CRYPT_INVALID_PACKET;
}
while(*pos != '\n'){
++pos;
}
i = 0;
while(*pos){
if(*pos == '-'){
break;
}
if(*pos > ' ' && *pos <= 'z'){
assemblybuf[i] = *pos;
++i;
}
++pos;
}
return base64_decode(assemblybuf, i, dercert, (long unsigned int*)derlen);
}
qboolean Sec_VerifyMemory(const char* expectedb64hash, void* memory, int lenmem)
{
unsigned char dercert[16384];
unsigned int dercertlen;
byte cleartext[16384];
byte ciphertext[0x20000];
unsigned long cleartextlen, ciphertextlen;
int decryptstat;
int sta;
char hash[1025];
long unsigned int sizeofhash;
rsa_key rsakey;
dercertlen = sizeof(dercert);
if(Sec_Pem2Der(cod4xpem, strlen(cod4xpem), dercert, &dercertlen) != CRYPT_OK){
Com_PrintError("Pem to Der conversion failed\n");
return qfalse;
}
ciphertextlen = sizeof(ciphertext);
if(base64_decode((byte*)expectedb64hash, strlen((char*)expectedb64hash), ciphertext, (long unsigned int*)&ciphertextlen) != CRYPT_OK)
{
Com_DPrintf("Not a valid base64 text\n");
return qfalse;
}
if((sta = rsa_import(dercert, dercertlen, &rsakey)) != CRYPT_OK){
Com_PrintError("rsa_import failed with error code %d:%s\n", sta, Sec_CryptErrStr(sta));
return qfalse;
}
cleartextlen = sizeof(cleartext) -1;
sta = rsa_decrypt_puplickey_nnj(ciphertext, ciphertextlen, cleartext, &cleartextlen, &decryptstat, &rsakey);
rsa_free(&rsakey);
if(sta != CRYPT_OK || cleartextlen < 0 || cleartextlen > sizeof(cleartext) -1){
Com_PrintError("rsa_decrypt_puplickey_nnj failed with error code %d:%s\n", sta, Sec_CryptErrStr(sta));
return qfalse;
}
cleartext[cleartextlen] = '\0';
sizeofhash = sizeof(hash);
if(!Sec_HashMemory(SEC_HASH_SHA256, memory, lenmem, hash, &sizeofhash, qfalse)){
Com_PrintError("Hashing has failed with errorcode %s\n", Sec_CryptErrStr(SecCryptErr));
return qfalse;
}
if(Q_stricmp(hash, (char*)cleartext) != 0)
{
return qfalse;
}
return qtrue;
}
qboolean Sec_VerifyFile(const char* expectedb64hash, const wchar_t* filepath)
{
FILE *fp;
int readlen;
int len = FS_FOpenFileReadOSPathUni( filepath, &fp );
if(len < 1)
{
return qfalse;
}
unsigned char* data = malloc(len);
readlen = FS_ReadOSPath (data, len, fp);
if(readlen != len)
{
FS_FCloseFileOSPath(fp);
free(data);
return qfalse;
}
FS_FCloseFileOSPath(fp);
qboolean valid = Sec_VerifyMemory(expectedb64hash, data, readlen);
free(data);
return valid;
}