gwenhywfar  5.10.1
padd.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Mon Jan 05 2004
3  copyright : (C) 2004 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #define DISABLE_DEBUGLOG
31 
32 
33 #include "padd_p.h"
34 #include <gwenhywfar/misc.h>
35 #include <gwenhywfar/debug.h>
36 #include <gwenhywfar/error.h>
37 #include <gwenhywfar/cryptdefs.h>
38 #include <gwenhywfar/text.h>
39 
40 #include <string.h>
41 #include <stdlib.h>
42 
43 
44 static uint8_t nullarray[]= {0, 0, 0, 0, 0, 0, 0, 0};
45 
46 
47 /*
48  * This code has been taken from OpenHBCI (rsakey.cpp, written by Fabian
49  * Kaiser)
50  */
51 unsigned char GWEN_Padd_permutate(unsigned char input)
52 {
53  unsigned char leftNibble;
54  unsigned char rightNibble;
55  static const unsigned char lookUp[2][16] = {
56  {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
57  {14, 3, 5, 8, 9, 4, 2, 15, 0, 13, 11, 6, 7, 10, 12, 1}
58  };
59 
60  rightNibble = input & 15;
61  leftNibble = input & 240;
62  leftNibble = leftNibble / 16;
63  rightNibble = lookUp[1][rightNibble];
64  leftNibble = lookUp[1][leftNibble];
65  leftNibble = leftNibble * 16;
66 
67  return leftNibble + rightNibble;
68 }
69 
70 
71 
72 /*
73  * The original code (in C++) has been written by Fabian Kaiser for OpenHBCI
74  * (file rsakey.cpp). Translated to C by Martin Preuss
75  */
77 {
78  unsigned char *p;
79  unsigned int l;
80  unsigned int i;
81  unsigned char buffer[GWEN_PADD_ISO9796_KEYSIZE];
82  unsigned char hash[20];
83  unsigned char c;
84 
85  p=(unsigned char *)GWEN_Buffer_GetStart(src);
87  memmove(hash, p, l);
88 
89  /* src+src+src */
90  if (GWEN_Buffer_AppendBytes(src, (const char *)hash, l)) {
91  DBG_INFO(GWEN_LOGDOMAIN, "here");
92  return -1;
93  }
94 
95  if (GWEN_Buffer_AppendBytes(src, (const char *)hash, l)) {
96  DBG_INFO(GWEN_LOGDOMAIN, "here");
97  return -1;
98  }
99 
100  /* src=src(20,40) */
101  if (GWEN_Buffer_Crop(src, 20, 40)) {
102  DBG_INFO(GWEN_LOGDOMAIN, "here");
103  return -1;
104  }
105 
106  memset(buffer, 0, sizeof(buffer));
107 
108  /* append redundancy */
109  p=(unsigned char *)GWEN_Buffer_GetStart(src);
110  for (i=0; i<=47; i++) {
111  int j1, j2, j3;
112 
113  j1=1 + sizeof(buffer) - (2*i);
114  j2=40-i;
115  j3=sizeof(buffer) - (2*i);
116 
117  if (j1>=0 && j1<(int)sizeof(buffer) && j2>=0) {
118  buffer[j1]=p[j2];
119  }
120  if (j3>=0 && j3<(int)sizeof(buffer) && j2>=0) {
121  buffer[j3]=GWEN_Padd_permutate(p[j2]);
122  }
123  } /* for */
124 
125  /* copy last 16 bytes to the beginning */
126  memmove(buffer, buffer+(sizeof(buffer)-16), 16);
127 
128  p=buffer;
129  /* finish */
130  c=p[sizeof(buffer)-1];
131  c = (c & 15) * 16;
132  c += 6;
133  p[sizeof(buffer)-1]=c;
134  p[0] = p[0] & 127;
135  p[0] = p[0] | 64;
136  p[sizeof(buffer) - 40] = p[sizeof(buffer) - 40] ^ 1;
137 
138  GWEN_Buffer_Reset(src);
139  if (GWEN_Buffer_AppendBytes(src, (const char *)buffer, sizeof(buffer))) {
140  DBG_INFO(GWEN_LOGDOMAIN, "here");
141  return -1;
142  }
143 
144  return 0;
145 }
146 
147 
149 {
150  unsigned int diff;
151  char *p;
152  int i;
153 
154  if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)+12) {
155  /*DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");*/
156  return GWEN_ERROR_INVALID;
157  }
158 
159  /* add trailer */
160  GWEN_Buffer_AppendByte(buf, 0xbc);
161 
162  /* reset position to 0 */
163  GWEN_Buffer_Rewind(buf);
164 
165  /* insert room for header */
166  diff=dstSize-GWEN_Buffer_GetUsedBytes(buf)-11+1;
167  if (GWEN_Buffer_InsertRoom(buf, 1+diff+1+8)) {
169  "Could not insert room for %d bytes",
170  1+diff+1+8);
171  return GWEN_ERROR_GENERIC;
172  }
173 
174  /* insert header and more-data-bit */
175  p=GWEN_Buffer_GetStart(buf);
176  *(p++)=0x60;
177 
178  /* insert padding field */
179  for (i=0; i<diff; i++)
180  *(p++)=0x0;
181  *(p++)=0x01;
182 
183  /* insert 8 random bytes */
184  GWEN_Crypt_Random(2, (uint8_t *)p, 8);
185  for (i=0; i<8; i++) {
186  if (*p==0)
187  /* TODO: Need to find a better but yet fast way */
188  *p=0xff;
189  p++;
190  }
191 
192  return 0;
193 }
194 
195 
197 {
198  uint32_t l;
199  uint32_t realSize;
200  const uint8_t *p;
201 
203  if (l<11) {
204  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too few bytes");
205  return GWEN_ERROR_INVALID;
206  }
207 
208  p=(const uint8_t *)GWEN_Buffer_GetStart(buf);
209  if (*p!=0x60) {
210  DBG_ERROR(GWEN_LOGDOMAIN, "First byte is not a 0x60");
211  return GWEN_ERROR_BAD_DATA;
212  }
213  p++;
214  l=0;
215  while (*p==0x00) {
216  l++;
217  p++;
218  }
219  if (*p!=0x01) {
220  /*DBG_ERROR(GWEN_LOGDOMAIN, "First byte after padding is not a 0x01");*/
221  return GWEN_ERROR_BAD_DATA;
222  }
223 
224  realSize=GWEN_Buffer_GetUsedBytes(buf)-11-l;
225  GWEN_Buffer_Crop(buf, 10+l, realSize);
226 
227  return 0;
228 }
229 
230 
231 
233 {
234  unsigned char paddLength;
235  unsigned int i;
236 
237  paddLength=y-(GWEN_Buffer_GetUsedBytes(src) % y);
238  for (i=0; i<paddLength; i++)
239  GWEN_Buffer_AppendByte(src, paddLength);
240  return 0;
241 }
242 
243 
244 
246 {
247  const char *p;
248  unsigned int lastpos;
249  unsigned char paddLength;
250 
251  lastpos=GWEN_Buffer_GetUsedBytes(src);
252  if (lastpos<y) {
253  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
254  return -1;
255  }
256  lastpos--;
257 
258  p=GWEN_Buffer_GetStart(src)+lastpos;
259  paddLength=*p;
260  if (paddLength<1 || paddLength>y) {
261  DBG_ERROR(GWEN_LOGDOMAIN, "Invalid padding (%d bytes ?)", paddLength);
262  return -1;
263  }
264  GWEN_Buffer_Crop(src, 0, GWEN_Buffer_GetUsedBytes(src)-paddLength);
265  GWEN_Buffer_SetPos(src, lastpos-paddLength);
266  return 0;
267 }
268 
269 
270 
272 {
274 }
275 
276 
277 
279 {
281 }
282 
283 
284 
286 {
287  unsigned int diff;
288  char *p;
289 
290  if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) {
291  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");
292  return GWEN_ERROR_INVALID;
293  }
294  diff=dstSize-GWEN_Buffer_GetUsedBytes(buf);
295  if (diff<11) {
296  /* honour minimum padding length for BT 1 of 8 bytes, plus the
297  * leading and the trailing zero and the block type identifier */
299  "Buffer contains too many bytes (diff is <11)");
300  return GWEN_ERROR_INVALID;
301  }
302 
303  /* reset position to 0 */
304  GWEN_Buffer_Rewind(buf);
305  if (GWEN_Buffer_InsertRoom(buf, diff)) {
306  DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff);
307  return GWEN_ERROR_GENERIC;
308  }
309 
310  p=GWEN_Buffer_GetStart(buf);
311  *(p++)=0x00;
312  *(p++)=0x01; /* block type 01 */
313  if (diff>3) {
314  memset(p, 0xff, diff-3);
315  p+=diff-3;
316  }
317  *(p++)=0x00;
318 
319  return 0;
320 }
321 
322 
323 
325 {
326  unsigned int diff;
327  char *p;
328  int i;
329 
330  if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) {
331  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");
332  return GWEN_ERROR_INVALID;
333  }
334  diff=dstSize-GWEN_Buffer_GetUsedBytes(buf);
335  if (diff<11) {
336  /* honour minimum padding length for BT 1 of 8 bytes, plus the
337  * leading and the trailing zero and the block type identifier */
339  "Buffer contains too many bytes (diff is <11)");
340  return GWEN_ERROR_INVALID;
341  }
342 
343  /* reset position to 0 */
344  GWEN_Buffer_Rewind(buf);
345  if (GWEN_Buffer_InsertRoom(buf, diff)) {
346  DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff);
347  return GWEN_ERROR_GENERIC;
348  }
349 
350  p=GWEN_Buffer_GetStart(buf);
351  *(p++)=0x00;
352  *(p++)=0x02; /* block type 02 */
353  GWEN_Crypt_Random(2, (uint8_t *)p, diff-3);
354  for (i=0; i<diff-3; i++) {
355  if (*p==0)
356  /* TODO: Need to find a better but yet fast way */
357  *p=0xff;
358  p++;
359  }
360  *(p++)=0x00;
361 
362  return 0;
363 }
364 
365 
366 
368 {
369  char *p;
370  uint32_t len;
371  uint32_t paddBytes;
372 
373  assert(buf);
374  len=GWEN_Buffer_GetUsedBytes(buf);
375  assert(len);
376 
377  p=GWEN_Buffer_GetStart(buf);
378  if (*p==0) {
379  p++;
380  len--;
381  }
382  if (len<11) {
383  DBG_ERROR(GWEN_LOGDOMAIN, "Too few bytes left (%d)", len);
384  return GWEN_ERROR_INVALID;
385  }
386 
387  if (*p!=0x01 && *p!=0x02) {
388  DBG_ERROR(GWEN_LOGDOMAIN, "Unsupported block type %02x", *p);
389  return GWEN_ERROR_INVALID;
390  }
391  p++;
392  len--;
393 
394  /* skip padding bytes */
395  paddBytes=0;
396  while (*p!=0x00 && len) {
397  p++;
398  len--;
399  paddBytes++;
400  }
401 
402  if (*p!=0x00) {
403  DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding");
404  return GWEN_ERROR_INVALID;
405  }
406  p++;
407  len--;
408 
409  if (paddBytes<8) {
410  /* at least 8 padding bytes are needed */
411  DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding (too few padding bytes)");
412  return GWEN_ERROR_INVALID;
413  }
414 
415  GWEN_Buffer_Crop(buf, GWEN_Buffer_GetUsedBytes(buf)-len, len);
416 
417  return 0;
418 }
419 
420 
421 
423 {
425 }
426 
427 
428 
430 {
432 }
433 
434 
435 
436 int GWEN_Padd_MGF1(uint8_t *pDestBuffer,
437  uint32_t lDestBuffer,
438  const uint8_t *pSeed,
439  uint32_t lSeed,
440  GWEN_MDIGEST *md)
441 {
442  uint32_t bytesLeft=lDestBuffer;
443  uint32_t i;
444  uint8_t counter[4];
445  uint8_t *p;
446 
447  p=pDestBuffer;
448 
449  for (i=0; bytesLeft>0; i++) {
450  int rv;
451  uint32_t l;
452 
453  counter[0]= (uint8_t)((i>>24) & 0xff);
454  counter[1]= (uint8_t)((i>>16) & 0xff);
455  counter[2]= (uint8_t)((i>>8) & 0xff);
456  counter[3]= (uint8_t)(i & 0xff);
457 
458  rv=GWEN_MDigest_Begin(md);
459  if (rv<0) {
460  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
461  return rv;
462  }
463 
464  rv=GWEN_MDigest_Update(md, pSeed, lSeed);
465  if (rv<0) {
466  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
467  return rv;
468  }
469 
470  rv=GWEN_MDigest_Update(md, counter, 4);
471  if (rv<0) {
472  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
473  return rv;
474  }
475 
476  rv=GWEN_MDigest_End(md);
477  if (rv<0) {
478  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
479  return rv;
480  }
481 
483  if (bytesLeft<l)
484  l=bytesLeft;
485  memmove(p, GWEN_MDigest_GetDigestPtr(md), l);
486  bytesLeft-=l;
487  p+=l;
488  }
489 
490  return 0;
491 }
492 
493 
494 
495 int GWEN_Padd_AddPkcs1Pss(uint8_t *pDestBuffer,
496  GWEN_UNUSED uint32_t lDestBuffer,
497  uint32_t nbits,
498  const uint8_t *pHash,
499  uint32_t lHash,
500  uint32_t lSalt,
501  GWEN_MDIGEST *md)
502 {
503  uint32_t emLen;
504  uint8_t *pSalt=NULL;
505  uint8_t *pDB;
506  uint8_t *pDbMask;
507  uint32_t x;
508  uint32_t i;
509  uint8_t *p;
510  int rv;
511  uint8_t hashMBar[64];
512  int numberOfBitsInByte0;
513 
514  emLen=nbits/8;
515  if (nbits%8)
516  emLen++;
517 
518  /* adjust emLen because the maximum number of bits in emLen is length of modulus-1 */
519  numberOfBitsInByte0=((nbits-1) & 0x07);
520  if (numberOfBitsInByte0==0) {
521  *(pDestBuffer++)=0;
522  emLen--;
523  }
524 
525  /* generate salt */
526  pSalt=(uint8_t *) malloc(lSalt);
527  assert(pSalt);
528  GWEN_Crypt_Random(2, pSalt, lSalt);
529 
530  /* M'=00 00 00 00 00 00 00 00 | HASH(M) | SALT */
531  rv=GWEN_MDigest_Begin(md);
532  if (rv<0) {
533  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
534  free(pSalt);
535  return rv;
536  }
537 
538  rv=GWEN_MDigest_Update(md, nullarray, 8);
539  if (rv<0) {
540  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
541  free(pSalt);
542  return rv;
543  }
544 
545  rv=GWEN_MDigest_Update(md, pHash, lHash);
546  if (rv<0) {
547  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
548  free(pSalt);
549  return rv;
550  }
551 
552  rv=GWEN_MDigest_Update(md, pSalt, lSalt);
553  if (rv<0) {
554  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
555  free(pSalt);
556  return rv;
557  }
558 
559  rv=GWEN_MDigest_End(md);
560  if (rv<0) {
561  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
562  free(pSalt);
563  return rv;
564  }
565  /* hashMBar=HASH(M') */
566  memmove(hashMBar,
569 
570  /* generate DB (PS | '01' | SALT) */
571  x=emLen-GWEN_MDigest_GetDigestSize(md)-lSalt-2;
572  pDB=(uint8_t *)malloc(emLen);
573  assert(pDB);
574  p=pDB;
575  memset(p, 0, x);
576  p+=x;
577  *(p++)=0x01;
578  memmove(p, pSalt, lSalt);
579  p+=lSalt;
580 
581  /* create DBMask */
582  x=emLen-GWEN_MDigest_GetDigestSize(md)-1;
583  pDbMask=(uint8_t *)malloc(x);
584  rv=GWEN_Padd_MGF1(pDbMask, x,
585  hashMBar, GWEN_MDigest_GetDigestSize(md),
586  md);
587  if (rv<0) {
588  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
589  free(pDbMask);
590  free(pDB);
591  free(pSalt);
592  return rv;
593  }
594 
595  /* created maskedDB in destination buffer */
596  p=pDestBuffer;
597  for (i=0; i<x; i++)
598  *(p++)=pDB[i] ^ pDbMask[i];
599 
600  /* append hashMBar */
601  memmove(p, hashMBar, GWEN_MDigest_GetDigestSize(md));
603  /* append '0xbc' */
604  *(p++)=0xbc;
605 
606  /* adjust first byte */
607  if (numberOfBitsInByte0)
608  pDestBuffer[0] &= 0xff >> (8-numberOfBitsInByte0);
609 
610  free(pDbMask);
611  free(pDB);
612  free(pSalt);
613 
614  return emLen;
615 }
616 
617 
618 
619 int GWEN_Padd_VerifyPkcs1Pss(const uint8_t *pSrcBuffer,
620  uint32_t lSrcBuffer,
621  uint32_t nbits,
622  const uint8_t *pHash,
623  uint32_t lHash,
624  uint32_t lSalt,
625  GWEN_MDIGEST *md)
626 {
627  uint32_t emLen;
628  const uint8_t *pSalt;
629  uint8_t *pDB;
630  uint32_t x;
631  uint32_t i;
632  int rv;
633  const uint8_t *hashMBar;
634  int numberOfBitsInByte0;
635 
636  emLen=nbits/8;
637  if (nbits%8)
638  emLen++;
639 
640  /* check for leading bits to be zero */
641  numberOfBitsInByte0=((nbits-1) & 0x07);
642 
643  if (numberOfBitsInByte0==0) {
644  pSrcBuffer++;
645  emLen--;
646  }
647  else {
648  if (pSrcBuffer[0] & (0xff << numberOfBitsInByte0)) {
649  DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: leading bits must be zero (%d)", numberOfBitsInByte0);
650  return GWEN_ERROR_BAD_DATA;
651  }
652  }
653 
654  /* check for key length */
655  if (emLen < (GWEN_MDigest_GetDigestSize(md)+lSalt+2)) {
656  DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: Key too small for data");
657  return GWEN_ERROR_BAD_DATA;
658  }
659 
660  /* check for length of provided data */
661  if (lSrcBuffer < emLen) {
662  DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: Provided data too small (is %d, expected %d)",
663  lSrcBuffer, emLen);
664  return GWEN_ERROR_BAD_DATA;
665  }
666 
667  /* get DB (PS | '01' | SALT) */
668  x=emLen-GWEN_MDigest_GetDigestSize(md)-1;
669 
670  pDB=(uint8_t *)malloc(x);
671  hashMBar=pSrcBuffer+x;
672  rv=GWEN_Padd_MGF1(pDB, x,
673  hashMBar, GWEN_MDigest_GetDigestSize(md),
674  md);
675  if (rv<0) {
676  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
677  free(pDB);
678  return rv;
679  }
680 
681  /* un-XOR DB using DBMask from source buffer (EM) */
682  for (i=0; i<x; i++)
683  pDB[i] ^= pSrcBuffer[i];
684 
685  /* check for leading bits */
686  if (numberOfBitsInByte0)
687  pDB[0] &= (0xff >> (8-numberOfBitsInByte0));
688 
689  /* pDB now contains PS | '01' | SALT */
690 
691  /* recover salt: skip all '00' and wait for '01' */
692  for (i=0; (i<(x-1) && pDB[i]==0); i++);
693  /* i now points to a byte which is not zero, expect it to be '01' */
694  if (pDB[i]!=0x01) {
695  DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: byte 0x01 missing before salt");
696  free(pDB);
697  return GWEN_ERROR_BAD_DATA;
698  }
699  i++;
700 
701  /* check for length of salt */
702  if ((x-i)!=lSalt) {
703  DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: bad length for salt (is %d, should be %d)",
704  x-i, lSalt);
705  free(pDB);
706  return GWEN_ERROR_BAD_DATA;
707  }
708 
709  /* get pointer to salt */
710  pSalt=pDB+i;
711 
712  /* M'=00 00 00 00 00 00 00 00 | HASH(M) | SALT */
713  rv=GWEN_MDigest_Begin(md);
714  if (rv<0) {
715  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
716  free(pDB);
717  return rv;
718  }
719 
720  rv=GWEN_MDigest_Update(md, nullarray, 8);
721  if (rv<0) {
722  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
723  free(pDB);
724  return rv;
725  }
726 
727  if (lHash) {
728  rv=GWEN_MDigest_Update(md, pHash, lHash);
729  if (rv<0) {
730  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
731  free(pDB);
732  return rv;
733  }
734  }
735 
736  rv=GWEN_MDigest_Update(md, pSalt, lSalt);
737  if (rv<0) {
738  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
739  free(pDB);
740  return rv;
741  }
742 
743  rv=GWEN_MDigest_End(md);
744  if (rv<0) {
745  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
746  free(pDB);
747  return rv;
748  }
749  if (memcmp(hashMBar,
751  GWEN_MDigest_GetDigestSize(md))!=0) {
752  DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: hash does not match");
753 
754  free(pDB);
755  return GWEN_ERROR_VERIFY;
756  }
757 
758  free(pDB);
759 
760  DBG_INFO(GWEN_LOGDOMAIN, "Hash ok.");
761  return 0;
762 }
763 
764 
765 
767 {
768  int rv;
769  unsigned int diff;
770  unsigned int bsize;
771  unsigned int dstSize;
772  unsigned int chunkSize;
774 
775  assert(a);
776  assert(buf);
777 
779  if (aid==GWEN_Crypt_PaddAlgoId_None)
780  /* short return if there is no padding to be done */
781  return 0;
782 
783  chunkSize=GWEN_Crypt_PaddAlgo_GetPaddSize(a);
784  if (chunkSize==0) {
785  DBG_ERROR(GWEN_LOGDOMAIN, "Invalid chunk size (0)");
786  return GWEN_ERROR_INVALID;
787  }
788 
789  bsize=GWEN_Buffer_GetUsedBytes(buf);
790  dstSize=bsize+(chunkSize-1);
791  dstSize=(dstSize/chunkSize)*chunkSize;
792  diff=dstSize-bsize;
793 
794  DBG_INFO(GWEN_LOGDOMAIN, "Padding with algo \"%s\"",
796 
797  switch (aid) {
798  case GWEN_Crypt_PaddAlgoId_None:
799  rv=0;
800  break;
801 
802  case GWEN_Crypt_PaddAlgoId_Iso9796_1A4:
803  if (dstSize>96) {
805  "Padding size must be <=96 bytes (is %d)",
806  dstSize);
807  return GWEN_ERROR_INVALID;
808  }
810  break;
811 
812  case GWEN_Crypt_PaddAlgoId_Pkcs1_1:
813  rv=GWEN_Padd_PaddWithPkcs1Bt1(buf, dstSize);
814  break;
815 
816  case GWEN_Crypt_PaddAlgoId_Pkcs1_2:
817  rv=GWEN_Padd_PaddWithPkcs1Bt2(buf, dstSize);
818  break;
819 
820  case GWEN_Crypt_PaddAlgoId_LeftZero:
821  rv=GWEN_Buffer_FillLeftWithBytes(buf, 0, diff);
822  break;
823 
824  case GWEN_Crypt_PaddAlgoId_RightZero:
825  rv=GWEN_Buffer_FillWithBytes(buf, 0, diff);
826  break;
827 
828  case GWEN_Crypt_PaddAlgoId_AnsiX9_23:
829  return GWEN_Padd_PaddWithAnsiX9_23(buf);
830 
831  case GWEN_Crypt_PaddAlgoId_Iso9796_2:
832  return GWEN_Padd_PaddWithIso9796_2(buf, dstSize);
833 
834  case GWEN_Crypt_PaddAlgoId_Iso9796_1:
835  default:
836  DBG_INFO(GWEN_LOGDOMAIN, "Algo-Type %d (%s) not supported",
839  }
840 
841  if (rv) {
842  DBG_ERROR(GWEN_LOGDOMAIN, "Error padding with algo %d (%s)",
844  return GWEN_ERROR_GENERIC;
845  }
846 
847  return rv;
848 }
849 
850 
851 
853 {
854  int rv;
856 
857  assert(a);
858  assert(buf);
859 
861  DBG_INFO(GWEN_LOGDOMAIN, "Unpadding with algo \"%s\"",
863 
864  switch (aid) {
865  case GWEN_Crypt_PaddAlgoId_None:
866  rv=0;
867  break;
868 
869  case GWEN_Crypt_PaddAlgoId_Pkcs1_1:
871  break;
872 
873  case GWEN_Crypt_PaddAlgoId_Pkcs1_2:
875  break;
876 
877  case GWEN_Crypt_PaddAlgoId_AnsiX9_23:
878  return GWEN_Padd_UnpaddWithAnsiX9_23(buf);
879 
880  case GWEN_Crypt_PaddAlgoId_Iso9796_2:
881  return GWEN_Padd_UnpaddWithIso9796_2(buf);
882 
883  case GWEN_Crypt_PaddAlgoId_Iso9796_1:
884  case GWEN_Crypt_PaddAlgoId_LeftZero:
885  case GWEN_Crypt_PaddAlgoId_RightZero:
886  case GWEN_Crypt_PaddAlgoId_Iso9796_1A4:
887  default:
888  DBG_INFO(GWEN_LOGDOMAIN, "Algo-Type %d (%s) not supported",
891  }
892 
893  if (rv) {
894  DBG_ERROR(GWEN_LOGDOMAIN, "Error padding with algo %d (%s)",
896  return GWEN_ERROR_GENERIC;
897  }
898 
899  return rv;
900 }
901 
902 
903 
905 {
906  return GWEN_Padd_PaddWithZkaToMultipleOf(src, 16);
907 }
908 
909 
910 
912 {
913  unsigned char paddLength;
914  unsigned int i;
915 
916  paddLength=y-(GWEN_Buffer_GetUsedBytes(src) % y);
917  if (paddLength>0) {
918  GWEN_Buffer_AppendByte(src, 0x80);
919  for (i=1; i<paddLength; i++)
920  GWEN_Buffer_AppendByte(src, 0x0);
921  }
922  return 0;
923 }
924 
925 
926 
928 {
929  const uint8_t *p;
930  unsigned int lastpos;
931  unsigned char paddLength;
932  paddLength=0;
933 
934  lastpos=GWEN_Buffer_GetUsedBytes(buf);
935  if (lastpos<y) {
936  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
937  return -1;
938  }
939  lastpos--;
940  p=(const uint8_t *)GWEN_Buffer_GetStart(buf)+lastpos;
941 
942  while (*p==0x00) {
943  paddLength++;
944  p--;
945  }
946 
947  /* first pad byte must be 0x80 */
948  if (*p==0x80) {
949  paddLength++;
950  p--;
951  }
952  else if (paddLength>0) {
953  DBG_ERROR(GWEN_LOGDOMAIN, "Invalid padding, first pad byte has wrong value %xd (%d bytes ?)", *p, paddLength);
954  return -1;
955  }
956 
957  if (paddLength<0 || paddLength>y) {
958  DBG_ERROR(GWEN_LOGDOMAIN, "Invalid padding (%d bytes ?)", paddLength);
959  return -1;
960  }
961  GWEN_Buffer_Crop(buf, 0, GWEN_Buffer_GetUsedBytes(buf)-paddLength);
962  GWEN_Buffer_SetPos(buf, lastpos-paddLength);
963  return 0;
964 }
965 
966 
967 
969 {
971 }
972 
973 
int GWEN_Padd_UnpaddWithZka(GWEN_BUFFER *buf)
Definition: padd.c:968
int GWEN_Buffer_FillLeftWithBytes(GWEN_BUFFER *bf, unsigned char c, uint32_t size)
Definition: buffer.c:1041
int GWEN_Crypt_PaddAlgo_GetPaddSize(const GWEN_CRYPT_PADDALGO *a)
Definition: paddalgo.c:195
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
int GWEN_Padd_PaddWithAnsiX9_23ToMultipleOf(GWEN_BUFFER *src, int y)
Definition: padd.c:232
int GWEN_Padd_UnpaddWithPkcs1Bt2(GWEN_BUFFER *src)
Definition: padd.c:429
int GWEN_Padd__UnpaddWithPkcs1Bt1Or2(GWEN_BUFFER *buf)
Definition: padd.c:367
int GWEN_Padd_MGF1(uint8_t *pDestBuffer, uint32_t lDestBuffer, const uint8_t *pSeed, uint32_t lSeed, GWEN_MDIGEST *md)
Definition: padd.c:436
int GWEN_Padd_PaddWithZka(GWEN_BUFFER *src)
Definition: padd.c:904
#define GWEN_ERROR_INVALID
Definition: error.h:67
uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf)
Definition: buffer.c:277
int GWEN_Padd_PaddWithISO9796(GWEN_BUFFER *src)
Definition: padd.c:76
#define NULL
Definition: binreloc.c:300
struct GWEN_CRYPT_PADDALGO GWEN_CRYPT_PADDALGO
Definition: paddalgo.h:21
int GWEN_Padd_PaddWithPkcs1Bt1(GWEN_BUFFER *buf, int dstSize)
Definition: padd.c:285
#define GWEN_LOGDOMAIN
Definition: logger.h:35
int GWEN_MDigest_Update(GWEN_MDIGEST *md, const uint8_t *buf, unsigned int l)
Definition: mdigest.c:153
int GWEN_Padd_UnapplyPaddAlgo(const GWEN_CRYPT_PADDALGO *a, GWEN_BUFFER *buf)
Definition: padd.c:852
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:650
int GWEN_Padd_PaddWithPkcs1Bt2(GWEN_BUFFER *buf, int dstSize)
Definition: padd.c:324
uint8_t * GWEN_MDigest_GetDigestPtr(GWEN_MDIGEST *md)
Definition: mdigest.c:81
#define GWEN_ERROR_BAD_DATA
Definition: error.h:121
int GWEN_MDigest_Begin(GWEN_MDIGEST *md)
Definition: mdigest.c:129
static uint8_t nullarray[]
Definition: padd.c:44
int GWEN_Padd_UnpaddWithIso9796_2(GWEN_BUFFER *buf)
Definition: padd.c:196
unsigned char GWEN_Padd_permutate(unsigned char input)
Definition: padd.c:51
int GWEN_Padd_PaddWithAnsiX9_23(GWEN_BUFFER *src)
Definition: padd.c:271
#define GWEN_ERROR_GENERIC
Definition: error.h:62
int GWEN_Padd_PaddWithZkaToMultipleOf(GWEN_BUFFER *src, int y)
Definition: padd.c:911
int GWEN_Padd_UnpaddWithAnsiX9_23FromMultipleOf(GWEN_BUFFER *src, int y)
Definition: padd.c:245
int GWEN_Padd_ApplyPaddAlgo(const GWEN_CRYPT_PADDALGO *a, GWEN_BUFFER *buf)
Definition: padd.c:766
struct GWEN_MDIGEST GWEN_MDIGEST
Definition: mdigest.h:25
const char * GWEN_Crypt_PaddAlgoId_toString(GWEN_CRYPT_PADDALGOID a)
Definition: paddalgo.c:58
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:394
GWEN_CRYPT_PADDALGOID GWEN_Crypt_PaddAlgo_GetId(const GWEN_CRYPT_PADDALGO *a)
Definition: paddalgo.c:186
int GWEN_Padd_PaddWithIso9796_2(GWEN_BUFFER *buf, int dstSize)
Definition: padd.c:148
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
int GWEN_Buffer_Crop(GWEN_BUFFER *bf, uint32_t pos, uint32_t l)
Definition: buffer.c:947
void GWEN_Crypt_Random(int quality, uint8_t *buffer, uint32_t len)
Definition: cryptdefs.c:551
int GWEN_MDigest_End(GWEN_MDIGEST *md)
Definition: mdigest.c:141
GWEN_CRYPT_PADDALGOID
Definition: paddalgo.h:60
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
unsigned int GWEN_MDigest_GetDigestSize(GWEN_MDIGEST *md)
Definition: mdigest.c:90
int GWEN_Buffer_SetPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:261
int GWEN_Padd_UnpaddWithPkcs1Bt1(GWEN_BUFFER *src)
Definition: padd.c:422
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
int GWEN_Padd_AddPkcs1Pss(uint8_t *pDestBuffer, GWEN_UNUSED uint32_t lDestBuffer, uint32_t nbits, const uint8_t *pHash, uint32_t lHash, uint32_t lSalt, GWEN_MDIGEST *md)
Definition: padd.c:495
int GWEN_Padd_VerifyPkcs1Pss(const uint8_t *pSrcBuffer, uint32_t lSrcBuffer, uint32_t nbits, const uint8_t *pHash, uint32_t lHash, uint32_t lSalt, GWEN_MDIGEST *md)
Definition: padd.c:619
int GWEN_Buffer_FillWithBytes(GWEN_BUFFER *bf, unsigned char c, uint32_t size)
Definition: buffer.c:1009
int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition: buffer.c:361
#define GWEN_ERROR_VERIFY
Definition: error.h:104
void GWEN_Buffer_Rewind(GWEN_BUFFER *bf)
Definition: buffer.c:660
int GWEN_Buffer_InsertRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:736
#define GWEN_ERROR_NOT_AVAILABLE
Definition: error.h:64
#define GWEN_UNUSED
int GWEN_Padd_UnpaddWithZkaFromMultipleOf(GWEN_BUFFER *buf, int y)
Definition: padd.c:927
int GWEN_Padd_UnpaddWithAnsiX9_23(GWEN_BUFFER *src)
Definition: padd.c:278