1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/util/dersubr.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,246 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "secder.h" 1.9 +#include <limits.h> 1.10 +#include "secerr.h" 1.11 + 1.12 +int 1.13 +DER_LengthLength(PRUint32 len) 1.14 +{ 1.15 + if (len > 127) { 1.16 + if (len > 255) { 1.17 + if (len > 65535L) { 1.18 + if (len > 16777215L) { 1.19 + return 5; 1.20 + } else { 1.21 + return 4; 1.22 + } 1.23 + } else { 1.24 + return 3; 1.25 + } 1.26 + } else { 1.27 + return 2; 1.28 + } 1.29 + } else { 1.30 + return 1; 1.31 + } 1.32 +} 1.33 + 1.34 +unsigned char * 1.35 +DER_StoreHeader(unsigned char *buf, unsigned int code, PRUint32 len) 1.36 +{ 1.37 + unsigned char b[4]; 1.38 + 1.39 + b[0] = (unsigned char)(len >> 24); 1.40 + b[1] = (unsigned char)(len >> 16); 1.41 + b[2] = (unsigned char)(len >> 8); 1.42 + b[3] = (unsigned char)len; 1.43 + if ((code & DER_TAGNUM_MASK) == DER_SET 1.44 + || (code & DER_TAGNUM_MASK) == DER_SEQUENCE) 1.45 + code |= DER_CONSTRUCTED; 1.46 + *buf++ = code; 1.47 + if (len > 127) { 1.48 + if (len > 255) { 1.49 + if (len > 65535) { 1.50 + if (len > 16777215) { 1.51 + *buf++ = 0x84; 1.52 + *buf++ = b[0]; 1.53 + *buf++ = b[1]; 1.54 + *buf++ = b[2]; 1.55 + *buf++ = b[3]; 1.56 + } else { 1.57 + *buf++ = 0x83; 1.58 + *buf++ = b[1]; 1.59 + *buf++ = b[2]; 1.60 + *buf++ = b[3]; 1.61 + } 1.62 + } else { 1.63 + *buf++ = 0x82; 1.64 + *buf++ = b[2]; 1.65 + *buf++ = b[3]; 1.66 + } 1.67 + } else { 1.68 + *buf++ = 0x81; 1.69 + *buf++ = b[3]; 1.70 + } 1.71 + } else { 1.72 + *buf++ = b[3]; 1.73 + } 1.74 + return buf; 1.75 +} 1.76 + 1.77 +/* 1.78 + * XXX This should be rewritten, generalized, to take a long instead 1.79 + * of a PRInt32. 1.80 + */ 1.81 +SECStatus 1.82 +DER_SetInteger(PLArenaPool *arena, SECItem *it, PRInt32 i) 1.83 +{ 1.84 + unsigned char bb[4]; 1.85 + unsigned len; 1.86 + 1.87 + bb[0] = (unsigned char) (i >> 24); 1.88 + bb[1] = (unsigned char) (i >> 16); 1.89 + bb[2] = (unsigned char) (i >> 8); 1.90 + bb[3] = (unsigned char) (i); 1.91 + 1.92 + /* 1.93 + ** Small integers are encoded in a single byte. Larger integers 1.94 + ** require progressively more space. 1.95 + */ 1.96 + if (i < -128) { 1.97 + if (i < -32768L) { 1.98 + if (i < -8388608L) { 1.99 + len = 4; 1.100 + } else { 1.101 + len = 3; 1.102 + } 1.103 + } else { 1.104 + len = 2; 1.105 + } 1.106 + } else if (i > 127) { 1.107 + if (i > 32767L) { 1.108 + if (i > 8388607L) { 1.109 + len = 4; 1.110 + } else { 1.111 + len = 3; 1.112 + } 1.113 + } else { 1.114 + len = 2; 1.115 + } 1.116 + } else { 1.117 + len = 1; 1.118 + } 1.119 + it->data = (unsigned char*) PORT_ArenaAlloc(arena, len); 1.120 + if (!it->data) { 1.121 + return SECFailure; 1.122 + } 1.123 + it->len = len; 1.124 + PORT_Memcpy(it->data, bb + (4 - len), len); 1.125 + return SECSuccess; 1.126 +} 1.127 + 1.128 +/* 1.129 + * XXX This should be rewritten, generalized, to take an unsigned long instead 1.130 + * of a PRUint32. 1.131 + */ 1.132 +SECStatus 1.133 +DER_SetUInteger(PLArenaPool *arena, SECItem *it, PRUint32 ui) 1.134 +{ 1.135 + unsigned char bb[5]; 1.136 + int len; 1.137 + 1.138 + bb[0] = 0; 1.139 + bb[1] = (unsigned char) (ui >> 24); 1.140 + bb[2] = (unsigned char) (ui >> 16); 1.141 + bb[3] = (unsigned char) (ui >> 8); 1.142 + bb[4] = (unsigned char) (ui); 1.143 + 1.144 + /* 1.145 + ** Small integers are encoded in a single byte. Larger integers 1.146 + ** require progressively more space. 1.147 + */ 1.148 + if (ui > 0x7f) { 1.149 + if (ui > 0x7fff) { 1.150 + if (ui > 0x7fffffL) { 1.151 + if (ui >= 0x80000000L) { 1.152 + len = 5; 1.153 + } else { 1.154 + len = 4; 1.155 + } 1.156 + } else { 1.157 + len = 3; 1.158 + } 1.159 + } else { 1.160 + len = 2; 1.161 + } 1.162 + } else { 1.163 + len = 1; 1.164 + } 1.165 + 1.166 + it->data = (unsigned char *)PORT_ArenaAlloc(arena, len); 1.167 + if (it->data == NULL) { 1.168 + return SECFailure; 1.169 + } 1.170 + 1.171 + it->len = len; 1.172 + PORT_Memcpy(it->data, bb + (sizeof(bb) - len), len); 1.173 + 1.174 + return SECSuccess; 1.175 +} 1.176 + 1.177 +/* 1.178 +** Convert a der encoded *signed* integer into a machine integral value. 1.179 +** If an underflow/overflow occurs, sets error code and returns min/max. 1.180 +*/ 1.181 +long 1.182 +DER_GetInteger(const SECItem *it) 1.183 +{ 1.184 + long ival = 0; 1.185 + unsigned len = it->len; 1.186 + unsigned char *cp = it->data; 1.187 + unsigned long overflow = 0x1ffUL << (((sizeof(ival) - 1) * 8) - 1); 1.188 + unsigned long ofloinit; 1.189 + 1.190 + PORT_Assert(len); 1.191 + if (!len) { 1.192 + PORT_SetError(SEC_ERROR_INPUT_LEN); 1.193 + return 0; 1.194 + } 1.195 + 1.196 + if (*cp & 0x80) 1.197 + ival = -1L; 1.198 + ofloinit = ival & overflow; 1.199 + 1.200 + while (len) { 1.201 + if ((ival & overflow) != ofloinit) { 1.202 + PORT_SetError(SEC_ERROR_BAD_DER); 1.203 + if (ival < 0) { 1.204 + return LONG_MIN; 1.205 + } 1.206 + return LONG_MAX; 1.207 + } 1.208 + ival = ival << 8; 1.209 + ival |= *cp++; 1.210 + --len; 1.211 + } 1.212 + return ival; 1.213 +} 1.214 + 1.215 +/* 1.216 +** Convert a der encoded *unsigned* integer into a machine integral value. 1.217 +** If an overflow occurs, sets error code and returns max. 1.218 +*/ 1.219 +unsigned long 1.220 +DER_GetUInteger(SECItem *it) 1.221 +{ 1.222 + unsigned long ival = 0; 1.223 + unsigned len = it->len; 1.224 + unsigned char *cp = it->data; 1.225 + unsigned long overflow = 0xffUL << ((sizeof(ival) - 1) * 8); 1.226 + 1.227 + PORT_Assert(len); 1.228 + if (!len) { 1.229 + PORT_SetError(SEC_ERROR_INPUT_LEN); 1.230 + return 0; 1.231 + } 1.232 + 1.233 + /* Cannot put a negative value into an unsigned container. */ 1.234 + if (*cp & 0x80) { 1.235 + PORT_SetError(SEC_ERROR_BAD_DER); 1.236 + return 0; 1.237 + } 1.238 + 1.239 + while (len) { 1.240 + if (ival & overflow) { 1.241 + PORT_SetError(SEC_ERROR_BAD_DER); 1.242 + return ULONG_MAX; 1.243 + } 1.244 + ival = ival << 8; 1.245 + ival |= *cp++; 1.246 + --len; 1.247 + } 1.248 + return ival; 1.249 +}