1 /***************************************************************************
2 begin : Tue Mar 04 2008
3 copyright : (C) 2008 by Martin Preuss
4 email : martin@libchipcard.de
5
6 ***************************************************************************
7 * Please see toplevel file COPYING for license details *
8 ***************************************************************************/
9
10
11
12
EBC_Provider_SignMessage_X002(AB_PROVIDER * pro,EB_MSG * msg,AB_USER * u,xmlNodePtr node)13 static int EBC_Provider_SignMessage_X002(AB_PROVIDER *pro,
14 EB_MSG *msg,
15 AB_USER *u,
16 xmlNodePtr node)
17 {
18 EBC_PROVIDER *dp;
19 int rv;
20 GWEN_CRYPT_TOKEN *ct;
21 const GWEN_CRYPT_TOKEN_CONTEXT *ctx;
22 const GWEN_CRYPT_TOKEN_KEYINFO *ki;
23 uint32_t keyId;
24 GWEN_BUFFER *hbuf;
25 GWEN_BUFFER *bbuf;
26 xmlNodePtr nodeX = NULL;
27 xmlNodePtr nodeXX = NULL;
28 xmlNodePtr nodeXXX = NULL;
29 xmlNodePtr nodeXXXX = NULL;
30 xmlNsPtr ns;
31
32 assert(pro);
33 dp=GWEN_INHERIT_GETDATA(AB_PROVIDER, EBC_PROVIDER, pro);
34 assert(dp);
35
36 /* get crypt token and context */
37 rv=EBC_Provider_MountToken(pro, u, &ct, &ctx);
38 if (rv<0) {
39 DBG_INFO(AQEBICS_LOGDOMAIN, "here (%d)", rv);
40 return rv;
41 }
42
43 /* get key id */
44 keyId=GWEN_Crypt_Token_Context_GetAuthSignKeyId(ctx);
45 ki=GWEN_Crypt_Token_GetKeyInfo(ct,
46 keyId,
47 0xffffffff,
48 0);
49 if (ki==NULL) {
50 DBG_INFO(AQEBICS_LOGDOMAIN,
51 "Keyinfo %04x not found on crypt token [%s:%s]",
52 keyId,
53 GWEN_Crypt_Token_GetTypeName(ct),
54 GWEN_Crypt_Token_GetTokenName(ct));
55 GWEN_Crypt_Token_Close(ct, 0, 0);
56 return GWEN_ERROR_NOT_FOUND;
57 }
58
59 /* prepare signature nodes */
60 ns=xmlSearchNs(EB_Msg_GetDoc(msg), node, BAD_CAST "ds");
61 assert(ns);
62
63 /* build hash */
64 bbuf=GWEN_Buffer_new(0, 256, 0, 1);
65 rv=EB_Msg_BuildHashSha256(msg, bbuf);
66 if (rv) {
67 DBG_ERROR(AQEBICS_LOGDOMAIN, "Could not build hash");
68 GWEN_Buffer_free(bbuf);
69 return rv;
70 }
71
72 /* base64 encode */
73 hbuf=GWEN_Buffer_new(0, 256, 0, 1);
74 rv=GWEN_Base64_Encode((const uint8_t *)GWEN_Buffer_GetStart(bbuf),
75 GWEN_Buffer_GetUsedBytes(bbuf),
76 hbuf, 0);
77 if (rv<0) {
78 DBG_INFO(AQEBICS_LOGDOMAIN, "here (%d)", rv);
79 GWEN_Buffer_free(hbuf);
80 GWEN_Buffer_free(bbuf);
81 return rv;
82 }
83 GWEN_Buffer_free(bbuf);
84
85 /* create signature node */
86 nodeX=xmlNewChild(node, ns, BAD_CAST "SignedInfo", NULL);
87 nodeXX=xmlNewChild(nodeX, ns, BAD_CAST "CanonicalizationMethod", NULL);
88 xmlNewProp(nodeXX,
89 BAD_CAST "Algorithm",
90 BAD_CAST "http://www.w3.org/TR/2001/REC-xml-c14n-20010315");
91 nodeXX=xmlNewChild(nodeX, ns, BAD_CAST "SignatureMethod", NULL);
92 xmlNewProp(nodeXX,
93 BAD_CAST "Algorithm",
94 BAD_CAST "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
95 nodeXX=xmlNewChild(nodeX, ns, BAD_CAST "Reference", NULL);
96 xmlNewProp(nodeXX,
97 BAD_CAST "URI",
98 BAD_CAST "#xpointer(//*[@authenticate='true'])");
99 nodeXXX=xmlNewChild(nodeXX, ns, BAD_CAST "Transforms", NULL);
100 nodeXXXX=xmlNewChild(nodeXXX, ns, BAD_CAST "Transform", NULL);
101 xmlNewProp(nodeXXXX,
102 BAD_CAST "Algorithm",
103 BAD_CAST "http://www.w3.org/TR/2001/REC-xml-c14n-20010315");
104
105 nodeXXX=xmlNewChild(nodeXX, ns, BAD_CAST "DigestMethod", NULL);
106 xmlNewProp(nodeXXX,
107 BAD_CAST "Algorithm",
108 BAD_CAST "http://www.w3.org/2001/04/xmlenc#sha256");
109
110 /* store hash value */
111 xmlNewTextChild(nodeXX, ns,
112 BAD_CAST "DigestValue",
113 BAD_CAST GWEN_Buffer_GetStart(hbuf));
114 GWEN_Buffer_free(hbuf);
115
116 /* build hash over SignedInfo */
117 bbuf=GWEN_Buffer_new(0, 256, 0, 1);
118 rv=EB_Xml_BuildNodeHashSha256(nodeX, "#xpointer(//*)", bbuf);
119 if (rv<0) {
120 DBG_INFO(AQEBICS_LOGDOMAIN, "here (%d)", rv);
121 GWEN_Buffer_free(bbuf);
122 return rv;
123 }
124
125 /* sign hash */
126 if (1) {
127 GWEN_CRYPT_PADDALGO *algo;
128 int ksize;
129 uint32_t l;
130 const uint8_t prefix[]= {
131 0x30, 0x31, 0x30, 0x0d,
132 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
133 0x05, 0x00,
134 0x04, 0x20
135 };
136
137 /* add prefix to hash of SignedInfo */
138 hbuf=GWEN_Buffer_new(0, 256, 0, 1);
139 ksize=GWEN_Crypt_Token_KeyInfo_GetKeySize(ki);
140 GWEN_Buffer_AppendBytes(hbuf, (const char *)prefix, sizeof(prefix));
141 GWEN_Buffer_AppendBuffer(hbuf, bbuf);
142 GWEN_Buffer_Reset(bbuf);
143
144 /* select padd algo */
145 algo=GWEN_Crypt_PaddAlgo_new(GWEN_Crypt_PaddAlgoId_Pkcs1_1);
146 GWEN_Crypt_PaddAlgo_SetPaddSize(algo, ksize);
147
148 /* actually sign */
149 GWEN_Buffer_AllocRoom(bbuf, ksize+16);
150 l=GWEN_Buffer_GetMaxUnsegmentedWrite(bbuf);
151 rv=GWEN_Crypt_Token_Sign(ct, keyId,
152 algo,
153 (const uint8_t *)GWEN_Buffer_GetStart(hbuf),
154 GWEN_Buffer_GetUsedBytes(hbuf),
155 (uint8_t *)GWEN_Buffer_GetPosPointer(bbuf),
156 &l,
157 NULL, /* ignore seq counter */
158 0);
159 GWEN_Crypt_PaddAlgo_free(algo);
160 if (rv<0) {
161 DBG_INFO(AQEBICS_LOGDOMAIN, "here (%d)", rv);
162 GWEN_Buffer_free(bbuf);
163 GWEN_Buffer_free(hbuf);
164 return rv;
165 }
166 GWEN_Buffer_IncrementPos(bbuf, l);
167 GWEN_Buffer_AdjustUsedBytes(bbuf);
168
169 /* base 64 encode signature */
170 GWEN_Buffer_Reset(hbuf);
171 rv=GWEN_Base64_Encode((const uint8_t *)GWEN_Buffer_GetStart(bbuf),
172 GWEN_Buffer_GetUsedBytes(bbuf),
173 hbuf, 0);
174 if (rv<0) {
175 DBG_INFO(AQEBICS_LOGDOMAIN, "here (%d)", rv);
176 GWEN_Buffer_free(hbuf);
177 GWEN_Buffer_free(bbuf);
178 return rv;
179 }
180 GWEN_Buffer_free(bbuf);
181
182 /* store signature */
183 xmlNewTextChild(node, ns,
184 BAD_CAST "SignatureValue",
185 BAD_CAST GWEN_Buffer_GetStart(hbuf));
186 GWEN_Buffer_free(hbuf);
187 }
188
189 return 0;
190 }
191
192
193
194
195