1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/util/derdec.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,189 @@ 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 "secerr.h" 1.10 + 1.11 +static PRUint32 1.12 +der_indefinite_length(unsigned char *buf, unsigned char *end) 1.13 +{ 1.14 + PRUint32 len, ret, dataLen; 1.15 + unsigned char tag, lenCode; 1.16 + int dataLenLen; 1.17 + 1.18 + len = 0; 1.19 + while ( 1 ) { 1.20 + if ((buf + 2) > end) { 1.21 + return(0); 1.22 + } 1.23 + 1.24 + tag = *buf++; 1.25 + lenCode = *buf++; 1.26 + len += 2; 1.27 + 1.28 + if ( ( tag == 0 ) && ( lenCode == 0 ) ) { 1.29 + return(len); 1.30 + } 1.31 + 1.32 + if ( lenCode == 0x80 ) { /* indefinite length */ 1.33 + ret = der_indefinite_length(buf, end); /* recurse to find length */ 1.34 + if (ret == 0) 1.35 + return 0; 1.36 + len += ret; 1.37 + buf += ret; 1.38 + } else { /* definite length */ 1.39 + if (lenCode & 0x80) { 1.40 + /* Length of data is in multibyte format */ 1.41 + dataLenLen = lenCode & 0x7f; 1.42 + switch (dataLenLen) { 1.43 + case 1: 1.44 + dataLen = buf[0]; 1.45 + break; 1.46 + case 2: 1.47 + dataLen = (buf[0]<<8)|buf[1]; 1.48 + break; 1.49 + case 3: 1.50 + dataLen = ((unsigned long)buf[0]<<16)|(buf[1]<<8)|buf[2]; 1.51 + break; 1.52 + case 4: 1.53 + dataLen = ((unsigned long)buf[0]<<24)| 1.54 + ((unsigned long)buf[1]<<16)|(buf[2]<<8)|buf[3]; 1.55 + break; 1.56 + default: 1.57 + PORT_SetError(SEC_ERROR_BAD_DER); 1.58 + return SECFailure; 1.59 + } 1.60 + } else { 1.61 + /* Length of data is in single byte */ 1.62 + dataLen = lenCode; 1.63 + dataLenLen = 0; 1.64 + } 1.65 + 1.66 + /* skip this item */ 1.67 + buf = buf + dataLenLen + dataLen; 1.68 + len = len + dataLenLen + dataLen; 1.69 + } 1.70 + } 1.71 +} 1.72 + 1.73 +/* 1.74 +** Capture the next thing in the buffer. 1.75 +** Returns the length of the header and the length of the contents. 1.76 +*/ 1.77 +static SECStatus 1.78 +der_capture(unsigned char *buf, unsigned char *end, 1.79 + int *header_len_p, PRUint32 *contents_len_p) 1.80 +{ 1.81 + unsigned char *bp; 1.82 + unsigned char whole_tag; 1.83 + PRUint32 contents_len; 1.84 + int tag_number; 1.85 + 1.86 + if ((buf + 2) > end) { 1.87 + *header_len_p = 0; 1.88 + *contents_len_p = 0; 1.89 + if (buf == end) 1.90 + return SECSuccess; 1.91 + return SECFailure; 1.92 + } 1.93 + 1.94 + bp = buf; 1.95 + 1.96 + /* Get tag and verify that it is ok. */ 1.97 + whole_tag = *bp++; 1.98 + tag_number = whole_tag & DER_TAGNUM_MASK; 1.99 + 1.100 + /* 1.101 + * XXX This code does not (yet) handle the high-tag-number form! 1.102 + */ 1.103 + if (tag_number == DER_HIGH_TAG_NUMBER) { 1.104 + PORT_SetError(SEC_ERROR_BAD_DER); 1.105 + return SECFailure; 1.106 + } 1.107 + 1.108 + if ((whole_tag & DER_CLASS_MASK) == DER_UNIVERSAL) { 1.109 + /* Check that the universal tag number is one we implement. */ 1.110 + switch (tag_number) { 1.111 + case DER_BOOLEAN: 1.112 + case DER_INTEGER: 1.113 + case DER_BIT_STRING: 1.114 + case DER_OCTET_STRING: 1.115 + case DER_NULL: 1.116 + case DER_OBJECT_ID: 1.117 + case DER_SEQUENCE: 1.118 + case DER_SET: 1.119 + case DER_PRINTABLE_STRING: 1.120 + case DER_T61_STRING: 1.121 + case DER_IA5_STRING: 1.122 + case DER_VISIBLE_STRING: 1.123 + case DER_UTC_TIME: 1.124 + case 0: /* end-of-contents tag */ 1.125 + break; 1.126 + default: 1.127 + PORT_SetError(SEC_ERROR_BAD_DER); 1.128 + return SECFailure; 1.129 + } 1.130 + } 1.131 + 1.132 + /* 1.133 + * Get first byte of length code (might contain entire length, might not). 1.134 + */ 1.135 + contents_len = *bp++; 1.136 + 1.137 + /* 1.138 + * If the high bit is set, then the length is in multibyte format, 1.139 + * or the thing has an indefinite-length. 1.140 + */ 1.141 + if (contents_len & 0x80) { 1.142 + int bytes_of_encoded_len; 1.143 + 1.144 + bytes_of_encoded_len = contents_len & 0x7f; 1.145 + contents_len = 0; 1.146 + 1.147 + switch (bytes_of_encoded_len) { 1.148 + case 4: 1.149 + contents_len |= *bp++; 1.150 + contents_len <<= 8; 1.151 + /* fallthru */ 1.152 + case 3: 1.153 + contents_len |= *bp++; 1.154 + contents_len <<= 8; 1.155 + /* fallthru */ 1.156 + case 2: 1.157 + contents_len |= *bp++; 1.158 + contents_len <<= 8; 1.159 + /* fallthru */ 1.160 + case 1: 1.161 + contents_len |= *bp++; 1.162 + break; 1.163 + 1.164 + case 0: 1.165 + contents_len = der_indefinite_length (bp, end); 1.166 + if (contents_len) 1.167 + break; 1.168 + /* fallthru */ 1.169 + default: 1.170 + PORT_SetError(SEC_ERROR_BAD_DER); 1.171 + return SECFailure; 1.172 + } 1.173 + } 1.174 + 1.175 + if ((bp + contents_len) > end) { 1.176 + /* Ran past end of buffer */ 1.177 + PORT_SetError(SEC_ERROR_BAD_DER); 1.178 + return SECFailure; 1.179 + } 1.180 + 1.181 + *header_len_p = bp - buf; 1.182 + *contents_len_p = contents_len; 1.183 + 1.184 + return SECSuccess; 1.185 +} 1.186 + 1.187 +SECStatus 1.188 +DER_Lengths(SECItem *item, int *header_len_p, PRUint32 *contents_len_p) 1.189 +{ 1.190 + return(der_capture(item->data, &item->data[item->len], header_len_p, 1.191 + contents_len_p)); 1.192 +}