1 /*############################################################################
2 # Copyright 2016-2017 Intel Corporation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 ############################################################################*/
16 /// Message signing implementation.
17 /*!
18 * \file
19 *
20 * This file has a corresponding walk-through in the SDK documentation.
21 *
22 * Review the walk-through for correctness after making changes to this
23 * file.
24 */
25 #include "src/signmsg.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include "epid/common/file_parser.h"
30 #include "epid/member/api.h"
31 #include "src/prng.h"
32 #include "util/convutil.h"
33
SignMsg(void const * msg,size_t msg_len,void const * basename,size_t basename_len,unsigned char const * signed_sig_rl,size_t signed_sig_rl_size,unsigned char const * signed_pubkey,size_t signed_pubkey_size,unsigned char const * priv_key_ptr,size_t privkey_size,HashAlg hash_alg,MemberPrecomp * member_precomp,EpidSignature ** sig,size_t * sig_len,EpidCaCertificate const * cacert)34 EpidStatus SignMsg(void const* msg, size_t msg_len, void const* basename,
35 size_t basename_len, unsigned char const* signed_sig_rl,
36 size_t signed_sig_rl_size,
37 unsigned char const* signed_pubkey,
38 size_t signed_pubkey_size, unsigned char const* priv_key_ptr,
39 size_t privkey_size, HashAlg hash_alg,
40 MemberPrecomp* member_precomp, EpidSignature** sig,
41 size_t* sig_len, EpidCaCertificate const* cacert) {
42 EpidStatus sts = kEpidErr;
43 void* prng = NULL;
44 MemberCtx* member = NULL;
45 SigRl* sig_rl = NULL;
46
47 do {
48 GroupPubKey pub_key = {0};
49 PrivKey priv_key = {0};
50 MembershipCredential member_credential = {0};
51 size_t sig_rl_size = 0;
52 MemberParams params = {0};
53 size_t member_size = 0;
54
55 if (!sig) {
56 sts = kEpidBadArgErr;
57 break;
58 }
59
60 // authenticate and extract group public key
61 sts = EpidParseGroupPubKeyFile(signed_pubkey, signed_pubkey_size, cacert,
62 &pub_key);
63 if (kEpidNoErr != sts) {
64 break;
65 }
66 // handle compressed private key or membership credential
67 if (privkey_size == sizeof(PrivKey)) {
68 priv_key = *(PrivKey*)priv_key_ptr;
69 } else if (privkey_size == sizeof(CompressedPrivKey)) {
70 sts = EpidDecompressPrivKey(&pub_key, (CompressedPrivKey*)priv_key_ptr,
71 &priv_key);
72 if (kEpidNoErr != sts) {
73 break;
74 }
75 } else if (privkey_size == sizeof(MembershipCredential)) {
76 member_credential = *(MembershipCredential*)priv_key_ptr;
77 } else {
78 sts = kEpidErr;
79 break;
80 } // if (privkey_size == sizeof(PrivKey))
81
82 // acquire PRNG
83 sts = PrngCreate(&prng);
84 if (kEpidNoErr != sts) {
85 break;
86 }
87
88 SetMemberParams(&PrngGen, prng, NULL, ¶ms);
89 // create member
90 sts = EpidMemberGetSize(¶ms, &member_size);
91 if (kEpidNoErr != sts) {
92 break;
93 }
94 member = (MemberCtx*)calloc(1, member_size);
95 if (!member) {
96 sts = kEpidNoMemErr;
97 break;
98 }
99 sts = EpidMemberInit(¶ms, member);
100 if (kEpidNoErr != sts) {
101 break;
102 }
103
104 sts = EpidMemberSetHashAlg(member, hash_alg);
105 if (kEpidNoErr != sts) {
106 break;
107 }
108
109 if (privkey_size == sizeof(PrivKey) ||
110 privkey_size == sizeof(CompressedPrivKey)) {
111 sts = EpidProvisionKey(member, &pub_key, &priv_key, member_precomp);
112 if (kEpidNoErr != sts) {
113 break;
114 }
115 } else if (privkey_size == sizeof(MembershipCredential)) {
116 sts = EpidProvisionCredential(member, &pub_key, &member_credential,
117 member_precomp);
118 if (kEpidNoErr != sts) {
119 break;
120 }
121 } // if (privkey_size == sizeof(PrivKey))
122 // start member
123 sts = EpidMemberStartup(member);
124 if (kEpidNoErr != sts) {
125 break;
126 }
127
128 // register any provided basename as allowed
129 if (0 != basename_len) {
130 sts = EpidRegisterBasename(member, basename, basename_len);
131 if (kEpidNoErr != sts) {
132 break;
133 }
134 }
135
136 if (signed_sig_rl) {
137 // authenticate and determine space needed for SigRl
138 sts = EpidParseSigRlFile(signed_sig_rl, signed_sig_rl_size, cacert, NULL,
139 &sig_rl_size);
140 if (kEpidSigInvalid == sts) {
141 // authentication failure
142 break;
143 }
144 if (kEpidNoErr != sts) {
145 break;
146 }
147 sig_rl = calloc(1, sig_rl_size);
148 if (!sig_rl) {
149 sts = kEpidMemAllocErr;
150 break;
151 }
152
153 // fill the SigRl
154 sts = EpidParseSigRlFile(signed_sig_rl, signed_sig_rl_size, cacert,
155 sig_rl, &sig_rl_size);
156 if (kEpidSigInvalid == sts) {
157 // authentication failure
158 break;
159 }
160 if (kEpidNoErr != sts) {
161 break;
162 }
163
164 sts = EpidMemberSetSigRl(member, sig_rl, sig_rl_size);
165 if (kEpidNoErr != sts) {
166 break;
167 }
168 } // if (signed_sig_rl)
169
170 // Signature
171 // Note: Signature size must be computed after sig_rl is loaded.
172 *sig_len = EpidGetSigSize(sig_rl);
173
174 *sig = calloc(1, *sig_len);
175 if (!*sig) {
176 sts = kEpidMemAllocErr;
177 break;
178 }
179
180 // sign message
181 sts =
182 EpidSign(member, msg, msg_len, basename, basename_len, *sig, *sig_len);
183 if (kEpidNoErr != sts) {
184 break;
185 }
186 sts = kEpidNoErr;
187 } while (0);
188
189 PrngDelete(&prng);
190 EpidMemberDeinit(member);
191 if (member) free(member);
192
193 if (sig_rl) free(sig_rl);
194
195 return sts;
196 }
197