-
Notifications
You must be signed in to change notification settings - Fork 21
/
ecdsa_p256_sha256_openssl.c
151 lines (130 loc) · 3.87 KB
/
ecdsa_p256_sha256_openssl.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
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "openssl/bn.h"
#include "openssl/ec.h"
#include "openssl/ecdsa.h"
#include "openssl/obj_mac.h" // for NID_secp192k1
#include "openssl/sha.h"
#define HASH_SIZE 32
#define ECPARAMS NID_X9_62_prime256v1
void unhex(char* hex, unsigned char* in, size_t ilen)
{
for (size_t i = 0; i < ilen; ++i) {
sscanf(hex, "%2hhx", &in[i]);
hex += 2;
}
}
void printBN(BIGNUM *r)
{
char* out = BN_bn2hex(r);
const char *padding="0000000000000000000000000000000000000000000000000000000000000000";
int padLen1 = 64 - strlen(out);
if(padLen1 < 0) padLen1 = 0;
printf("%*.*s%s\n", padLen1, padLen1, padding, out);
OPENSSL_free(out);
}
int main(int argc, char* argv[])
{
// Our args
size_t blen = 0;
int success = 0;
uint8_t* hash;
int signing;
int hash_provided = 0;
// To handle the flags:
int c;
extern char* optarg;
extern int optind, optopt, opterr;
while ((c = getopt(argc, argv, ":h:")) != -1) {
switch (c) {
case 'h':
hash = (uint8_t*)malloc(strlen(optarg) / 2);
blen = strlen(optarg) / 2;
unhex(optarg, hash, blen); // unsafe for the memory, if optarg is bigger than hash!
hash_provided = 1;
break;
case ':':
// -h without hash
printf("-h without blen");
success = -1;
break;
case '?':
printf("unknown arg %c\n", optopt);
success = -1;
break;
}
}
if (argc - optind == 4) {
signing = 1;
} else if (argc - optind == 5) {
signing = 0;
} else {
printf("usage: \t%s X, Y, D, M\nor \t%s X, Y, R, S, M\n", argv[0], argv[0]);
return -1;
}
// Handle the hash value
if (hash_provided != 1) { // then we must hash our message, flag -h not provided
size_t tlen = strlen(argv[argc - 1]) / 2; // since it is an hexa string
uint8_t* nhex = (uint8_t*)malloc(tlen);
unhex(argv[argc - 1], nhex, tlen); // we convert from hex to bin
hash = (uint8_t*)malloc(HASH_SIZE);
SHA256(nhex, tlen, hash);
free(nhex);
blen = HASH_SIZE;
}
// OpenSSL stuff:
int ret;
ECDSA_SIG* sig;
EC_KEY* eckey;
BIGNUM* x = BN_new();
BIGNUM* y = BN_new();
BIGNUM* d = BN_new();
BN_hex2bn(&x, argv[optind]);
BN_hex2bn(&y, argv[optind + 1]);
eckey = EC_KEY_new_by_curve_name(ECPARAMS);
if (eckey == NULL) {
printf("Failed to create new EC Key for this curve.\n");
return -1;
}
if (!EC_KEY_set_public_key_affine_coordinates(eckey, x, y)) {
printf("Failed to create set EC Key with the provided args.\n");
return -1;
}
if (signing) {
BN_hex2bn(&d, argv[optind + 2]);
EC_KEY_set_private_key(eckey, d);
sig = ECDSA_do_sign(hash, blen, eckey); // this return a newly initialized ECDSA_SIG
if (sig == NULL) {
printf("Failed to sign with those args.\n");
return -1;
}
printBN(sig->r);
printBN(sig->s);
} else {
sig = ECDSA_SIG_new();
BN_hex2bn(&sig->r, argv[optind + 2]);
BN_hex2bn(&sig->s, argv[optind + 3]);
ret = ECDSA_do_verify(hash, blen, sig, eckey);
if (ret == -1) {
/* error */
printf(" failure ECDSA_do_verify returned -1");
success = -1;
} else if (ret == 0) /* then the signature is wrong */
{
printf("False\n");
} else /* ret == 1, so signature is okay */
{
printf("True\n");
}
}
ECDSA_SIG_free(sig);
EC_KEY_free(eckey);
BN_free(x);
BN_free(y);
BN_free(d);
free(hash);
return success;
}