Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat https://www.fefe.de/libowfat/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

43 lines
1.3 KiB

  1. #include "scan.h"
  2. /* ASN.1 DER tag encoding parser.
  3. * Write value as big endian series of bytes, each containing seven
  4. * bits. In each byte except the last, set the highest bit.
  5. * Examples:
  6. * 0 -> 0x00
  7. * 5 -> 0x05
  8. * 0xc2 -> 0x81 0x42 */
  9. size_t scan_asn1dertag(const char* src,size_t len,unsigned long long* length) {
  10. size_t n;
  11. unsigned long long l=0;
  12. if (len==0 || (unsigned char)src[0]==0x80) return 0; // catch non-minimal encoding
  13. for (n=0; n<len; ++n) {
  14. /* make sure we can represent the stored number in l */
  15. if (l>>(sizeof(l)*8-7)) return 0; // catch integer overflow
  16. l=(l<<7) | (src[n]&0x7f);
  17. /* if high bit not set, this is the last byte in the sequence */
  18. if (!(src[n]&0x80)) {
  19. *length=l;
  20. return n+1;
  21. }
  22. }
  23. return 0;
  24. }
  25. #ifdef UNITTEST
  26. #include <assert.h>
  27. int main() {
  28. unsigned long long i;
  29. assert(scan_asn1dertag("\x00",1,&i)==1 && i==0);
  30. assert(scan_asn1dertag("\x05",1,&i)==1 && i==5);
  31. assert(scan_asn1dertag("\x81\x42",2,&i)==2 && i==0xc2);
  32. assert(scan_asn1dertag("\x05",0,&i)==0); // truncated
  33. assert(scan_asn1dertag("\x81\x42",1,&i)==0); // truncated
  34. assert(scan_asn1dertag("\x80\x05",2,&i)==0); // non-minimal encoding
  35. assert(scan_asn1dertag("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",10,&i)==0); // value does not fit
  36. return 0;
  37. }
  38. #endif