1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 * 3 * LibTomCrypt is a library that provides various cryptographic 4 * algorithms in a highly modular and flexible manner. 5 * 6 * The library is free for all purposes without any express 7 * guarantee it works. 8 * 9 * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com 10 */ 11 #include "tomcrypt.h" 12 13 /** 14 @file der_encode_integer.c 15 ASN.1 DER, encode an integer, Tom St Denis 16 */ 17 18 19 #ifdef LTC_DER 20 21 /* Exports a positive bignum as DER format (upto 2^32 bytes in size) */ 22 /** 23 Store a mp_int integer 24 @param num The first mp_int to encode 25 @param out [out] The destination for the DER encoded integers 26 @param outlen [in/out] The max size and resulting size of the DER encoded integers 27 @return CRYPT_OK if successful 28 */ 29 int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen) 30 { 31 unsigned long tmplen, y; 32 int err, leading_zero; 33 34 LTC_ARGCHK(num != NULL); 35 LTC_ARGCHK(out != NULL); 36 LTC_ARGCHK(outlen != NULL); 37 38 /* find out how big this will be */ 39 if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) { 40 return err; 41 } 42 43 if (*outlen < tmplen) { 44 *outlen = tmplen; 45 return CRYPT_BUFFER_OVERFLOW; 46 } 47 48 if (mp_cmp_d(num, 0) != LTC_MP_LT) { 49 /* we only need a leading zero if the msb of the first byte is one */ 50 if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) { 51 leading_zero = 1; 52 } else { 53 leading_zero = 0; 54 } 55 56 /* get length of num in bytes (plus 1 since we force the msbyte to zero) */ 57 y = mp_unsigned_bin_size(num) + leading_zero; 58 } else { 59 leading_zero = 0; 60 y = mp_count_bits(num); 61 y = y + (8 - (y & 7)); 62 y = y >> 3; 63 if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --y; 64 } 65 66 /* now store initial data */ 67 *out++ = 0x02; 68 if (y < 128) { 69 /* short form */ 70 *out++ = (unsigned char)y; 71 } else if (y < 256) { 72 *out++ = 0x81; 73 *out++ = (unsigned char)y; 74 } else if (y < 65536UL) { 75 *out++ = 0x82; 76 *out++ = (unsigned char)((y>>8)&255); 77 *out++ = (unsigned char)y; 78 } else if (y < 16777216UL) { 79 *out++ = 0x83; 80 *out++ = (unsigned char)((y>>16)&255); 81 *out++ = (unsigned char)((y>>8)&255); 82 *out++ = (unsigned char)y; 83 } else { 84 return CRYPT_INVALID_ARG; 85 } 86 87 /* now store msbyte of zero if num is non-zero */ 88 if (leading_zero) { 89 *out++ = 0x00; 90 } 91 92 /* if it's not zero store it as big endian */ 93 if (mp_cmp_d(num, 0) == LTC_MP_GT) { 94 /* now store the mpint */ 95 if ((err = mp_to_unsigned_bin(num, out)) != CRYPT_OK) { 96 return err; 97 } 98 } else if (mp_iszero(num) != LTC_MP_YES) { 99 void *tmp; 100 101 /* negative */ 102 if (mp_init(&tmp) != CRYPT_OK) { 103 return CRYPT_MEM; 104 } 105 106 /* 2^roundup and subtract */ 107 y = mp_count_bits(num); 108 y = y + (8 - (y & 7)); 109 if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) y -= 8; 110 if (mp_2expt(tmp, y) != CRYPT_OK || mp_add(tmp, num, tmp) != CRYPT_OK) { 111 mp_clear(tmp); 112 return CRYPT_MEM; 113 } 114 if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { 115 mp_clear(tmp); 116 return err; 117 } 118 mp_clear(tmp); 119 } 120 121 /* we good */ 122 *outlen = tmplen; 123 return CRYPT_OK; 124 } 125 126 #endif 127 128 /* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c,v $ */ 129 /* $Revision: 1.8 $ */ 130 /* $Date: 2006/12/04 21:34:03 $ */ 131