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