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
|
/* Copyright 2017 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/crypto.h>
#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>
#include <openssl/objects.h>
#include "debug.h"
#include "utils.h"
#include "ossl_functions_ecc.h"
/* messages are traced here
All messages, even error messages, are traced only if verbose is set. There messages are
'techie' and should not be returned unless the user asks for them.
*/
extern FILE* messageFile;
extern int verbose;
long Ossl_VerifyECC(int *valid, /* output boolean */
const unsigned char *digest,
size_t digestLength,
const unsigned char *publicKey,
size_t publicKeyLength,
const unsigned char *signature,
unsigned long signatureLength)
{
long rc = 0; /* function return code */
int irc;
EC_KEY *ecPubKey = NULL; /* freed @1 */
if (verbose) fprintf(messageFile, "Ossl_VerifyECC: Verifying using OpenSSL\n");
if (verbose) PrintAll(messageFile, "Ossl_VerifyECC: public key", publicKeyLength, publicKey);
if (verbose) PrintAll(messageFile, "Ossl_VerifyECC: digest", digestLength, digest);
if (verbose) PrintAll(messageFile, "Ossl_VerifyECC: signature", signatureLength, signature);
/* create an EC public key token */
if (rc == 0) {
rc = Ossl_SetPubKey_ECC(&ecPubKey, /* freed @1 */
publicKey,
publicKeyLength);
}
/* verify signature */
if (rc == 0) {
if (verbose) fprintf(messageFile, "Ossl_VerifyECC: signature length out %lu\n",
signatureLength);
irc = ECDSA_verify(0, /* type ignored */
digest, /* digest to be verified*/
digestLength,
signature, /* DER encoded signature */
signatureLength, /* length of signature */
ecPubKey); /* public key */
if (irc == 0) {
if (verbose) fprintf(messageFile,
"Ossl_VerifyECC: ECDSA_verify failed\n");
*valid = FALSE;
}
else {
if (verbose) fprintf(messageFile,
"Ossl_VerifyECC: ECDSA_verify success\n");
*valid = TRUE;
}
}
/* cleanup */
if (ecPubKey != NULL) { /* @1 */
EC_KEY_free(ecPubKey);
}
return rc;
}
long Ossl_SetPubKey_ECC(EC_KEY **ecPubKey, /* freed by caller */
const unsigned char *publicKey,
size_t publicKeyLength)
{
long rc = 0;
int irc;
int nid;
EC_GROUP *group = NULL; /* freed @1 */
EC_POINT *ec_point = NULL; /* freed @2 */
if (verbose) fprintf(messageFile, "Ossl_SetPubKey_ECC: Creating public key token\n");
/* create an EC_KEY */
if (rc == 0) {
*ecPubKey = EC_KEY_new(); /* freed @5 */
if (*ecPubKey == NULL) {
fprintf(messageFile, "Ossl_SetPubKey_ECC: unable to EC_KEY_new\n");
rc = ERROR_CODE;
}
}
/* Creates a EC_GROUP object with a curve specified by a NID */
if (rc == 0) {
nid = NID_secp521r1; /* P-521 */
if (verbose) fprintf(messageFile, "Ossl_SetPubKey_ECC: nid %d %s\n", nid, OBJ_nid2sn(nid));
group = EC_GROUP_new_by_curve_name(nid); /* freed @1 */
if (group == NULL) {
fprintf(messageFile, "Ossl_SetPubKey_ECC: unable to EC_GROUP_new_by_curve_name\n");
rc = ERROR_CODE;
}
}
/* create a new EC_POINT */
if (rc == 0) {
ec_point = EC_POINT_new(group); /* freed @2 */
if (ec_point == NULL) {
fprintf(messageFile, "Ossl_SetPubKey_ECC: unable to EC_POINT_new\n");
rc = ERROR_CODE;
}
}
/* Sets the EC_GROUP P-521 of an EC_KEY object */
if (rc == 0) {
irc = EC_KEY_set_group(*ecPubKey, group);
if (irc == 0) {
fprintf(messageFile, "Ossl_SetPubKey_ECC: unable to EC_KEY_set_group\n");
rc = ERROR_CODE;
}
}
/* assign the public key to the EC_POINT */
if (rc == 0) {
/** Decodes a EC_POINT from a octet string
* \param group underlying EC_GROUP object
* \param p EC_POINT object
* \param buf memory buffer with the encoded ec point
* \param len length of the encoded ec point
* \param ctx BN_CTX object (optional)
* \return 1 on success and 0 if an error occured
*/
irc = EC_POINT_oct2point(group,
ec_point,
publicKey,
publicKeyLength,
NULL);
if (irc == 0) {
fprintf(messageFile, "Ossl_SetPubKey_ECC: unable to EC_POINT_oct2point\n");
rc = ERROR_CODE;
}
}
if (rc == 0) {
/** Sets the public key of a EC_KEY object.
* \param key EC_KEY object
* \param pub EC_POINT object with the public key (note: the EC_KEY object
* will use an own copy of the EC_POINT object).
* \return 1 on success and 0 if an error occurred.
*/
irc = EC_KEY_set_public_key(*ecPubKey, ec_point);
if (irc == 0) {
fprintf(messageFile, "Ossl_SetPubKey_ECC: unable to EC_KEY_set_public_key\n");
rc = ERROR_CODE;
}
}
/* sanity check */
if (rc == 0) {
/** Verifies that a private and/or public key is valid.
* \param key the EC_KEY object
* \return 1 on success and 0 otherwise.
*/
irc = EC_KEY_check_key(*ecPubKey);
if (irc == 0) {
fprintf(messageFile, "Ossl_SetPubKey_ECC: unable to EC_KEY_check_key\n");
rc = ERROR_CODE;
}
}
/* cleanup */
if (group != NULL) {
EC_GROUP_free(group); /* @1 */
}
if (ec_point != NULL) {
EC_POINT_free(ec_point); /* @2 */
}
return rc;
}
|