/* * Copyright (c) 2006, John P. T. Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "superapi.h" #define WORD_BIT 32 #define WORD_BYTE 4 #define EIGHT_BIT 8 #define SEVEN_BIT 7 #define FOUR_BIT 4 #define ONE_BIT 1 #define SIXTEEN_K (16*1024) static char hexchar[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /* stores number of bytes used to represent packet size */ #define TWO_BYTES 2 /* restricted to 2^30 - 1 */ static void encodeGeneralLengthDeterminant(packedEncode *memBuf, int n); static int decodeGeneralLengthDeterminant(packedDecode *memBuf); /* defined in encode.c */ extern int bitcount (unsigned int n); int writeMessage(int fd, char *buf, int bufsize) { unsigned short n; char *msg; int bytes; if ((msg = malloc(bufsize + TWO_BYTES)) == NULL) { perror("falied to malloc memory in writeMessage!"); exit(EXIT_FAILURE); } n = htons(bufsize); bcopy(&n, msg, TWO_BYTES); bcopy(buf, (msg + TWO_BYTES), bufsize); bytes = write(fd, msg, (bufsize + TWO_BYTES)); free(msg); return bytes; } int readMessage(int fd, char *buf, int bufsize) { int len; unsigned short data_size, n; char header_buffer[TWO_BYTES]; char *header_ptr, *data_ptr; header_ptr = header_buffer; while (header_ptr < header_buffer + TWO_BYTES) { if ((len = read(fd, header_ptr, TWO_BYTES)) > 0) header_ptr = header_ptr + len; else return -1; /* failed to read header */ } bcopy(header_buffer, &n, TWO_BYTES); data_size = ntohs(n); if (data_size > bufsize) { return -2; /* out of buffer */ } data_ptr = buf; while (data_ptr < buf + data_size) { if ((len = read(fd, data_ptr, data_size)) > 0) data_ptr = data_ptr + len; else return -3; /* failed to read data */ } /* return the byte size minus header */ return data_size; } /* N.B. this is not same method as PER standard */ static void encodeGeneralLengthDeterminant(packedEncode *memBuf, int n) { if (n <= 127) encode(memBuf, n, 8); else if (n > 127 && n < SIXTEEN_K) { encode(memBuf, 2, 2); encode(memBuf, n, 14); } else { /* must be >= SIXTEEN_K */ encode(memBuf, 3, 2); /* limitation of length encoding is 30 bits */ encode(memBuf, n, 30); } } /* N.B. this is not same method as PER standard */ int decodeGeneralLengthDeterminant(packedDecode *memBuf) { int len, n; /* check to see if first bit set to 0 to see if len <= 127 */ if (decode(memBuf, 1) == 0) len = decode(memBuf, 7); else { /* the next bit will determine what it could be */ n = decode(memBuf, 1); if (n == 0) len = decode(memBuf, 14); else len = decode(memBuf, 30); } return len; } void encodeBoolean(packedEncode *memBuf, int flag) { encode(memBuf, flag, 1); } int decodeBoolean(packedDecode *memBuf) { return (decode(memBuf, 1)); } void encodeConstrainedBitString(packedEncode *memBuf, char *s, int lb, int ub) { int bits, len, i; bits = bitcount(ub - lb + 1); len = strlen(s); /* encode length as constrained whole number */ encode(memBuf, len - lb, bits); for (i = 0; i < len; i++) { encode(memBuf, *(s+i) - '0', ONE_BIT); } } char *decodeConstrainedBitString(packedDecode *memBuf, char *s, int lb, int ub) { int len, i; char *baseptr; /* get length as constrained whole number */ len = decode(memBuf, bitcount(ub - lb + 1)) + lb; baseptr = s; #ifdef DEBUG puts("decodeConstrainedBitString"); printf("len = %d\n", len); #endif for (i = 0; i < len; i++) *s++ = decode(memBuf, ONE_BIT) + '0'; *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } void encodeFixedLengthBitString(packedEncode *memBuf, char *s, int len) { int i; #ifdef DEBUG puts("encodeFixedLengthBitString"); printf("s = %s\n", s); printf("len = %d\n", len); #endif for (i = 0; i < len; i++) { encode(memBuf, *(s+i) - '0', ONE_BIT); } } char *decodeFixedLengthBitString(packedDecode *memBuf, char *s, int len) { int i; char *baseptr; #ifdef DEBUG puts("decodeFixedLengthBitString"); printf("len = %d\n", len); #endif baseptr = s; for (i = 0; i < len; i++) *s++ = decode(memBuf, ONE_BIT) + '0'; *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } void encodeSemiConstrainedBitString(packedEncode *memBuf, char *s) { int len, i; len = strlen(s); #ifdef DEBUG puts("encodeSemiConstrainedBitString"); printf("s = %s\n", s); #endif /* first need to encode a length value of the string */ encodeGeneralLengthDeterminant(memBuf, len); #ifdef DEBUG printf("len = %d\n", len); #endif for (i = 0; i < len; i++) { encode(memBuf, *(s+i) - '0', ONE_BIT); } } char *decodeSemiConstrainedBitString(packedDecode *memBuf, char *s) { int len, i; char *baseptr; len = decodeGeneralLengthDeterminant(memBuf); #ifdef DEBUG puts("decodeSemiConstrainedBitString"); printf("len = %d\n", len); #endif baseptr = s; for (i = 0; i < len; i++) *s++ = decode(memBuf, ONE_BIT) + '0'; *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } void encodeFixedLengthHexString(packedEncode *memBuf, char *s, int len) { int i; char c; #ifdef DEBUG puts("encodeFixedLengthHexString"); printf("s = %s\n", s); printf("len = %d\n", len); #endif for (i = 0; i < len; i++) { c = *(s+i); if (c >= '0' && c <= '9') encode(memBuf, c - '0', FOUR_BIT); else if (c >= 'A' && c <= 'Z') encode(memBuf, c - 'A' + 10, FOUR_BIT); else if (c >= 'a' && c <= 'z') encode(memBuf, c - 'a' + 10, FOUR_BIT); else { printf("encodeFixedLengthHexString\n"); exit(EXIT_FAILURE); } } } char *decodeFixedLengthHexString(packedDecode *memBuf, char *s, int len) { int i; char *baseptr; #ifdef DEBUG puts("decodeFixedLengthHexString"); printf("len = %d\n", len); #endif baseptr = s; for (i = 0; i < len; i++) *s++ = hexchar[decode(memBuf, FOUR_BIT)]; *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } void encodeConstrainedHexString(packedEncode *memBuf, char *s, int lb, int ub) { int bits, len, i; char c; bits = bitcount(ub - lb + 1); len = strlen(s); /* encode length as constrained whole number */ encode(memBuf, len - lb, bits); #ifdef DEBUG puts("encodeConstrainedHexString"); printf("s = %s\n", s); printf("len = %d\n", len); #endif for (i = 0; i < len; i++) { c = *(s+i); if (c >= '0' && c <= '9') encode(memBuf, c - '0', FOUR_BIT); else if (c >= 'A' && c <= 'Z') encode(memBuf, c - 'A' + 10, FOUR_BIT); else if (c >= 'a' && c <= 'z') encode(memBuf, c - 'a' + 10, FOUR_BIT); else { printf("encodeConstrainedHexString\n"); exit(EXIT_FAILURE); } } } char *decodeConstrainedHexString(packedDecode *memBuf, char *s, int lb, int ub) { int len, i; char *baseptr; /* get length as constrained whole number */ len = decode(memBuf, bitcount(ub - lb + 1)) + lb; #ifdef DEBUG puts("decodeConstrainedHexString"); printf("len = %d\n", len); #endif baseptr = s; for (i = 0; i < len; i++) *s++ = hexchar[decode(memBuf, FOUR_BIT)]; *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } void encodeSemiConstrainedHexString(packedEncode *memBuf, char *s) { int len, i; char c; len = strlen(s); #ifdef DEBUG puts("encodeSemiConstrainedHexString"); printf("s = %s\n", s); #endif /* first need to encode a length value of the string */ encodeGeneralLengthDeterminant(memBuf, len); /* printf("len = %d\n", len); */ for (i = 0; i < len; i++) { c = *(s+i); if (c >= '0' && c <= '9') encode(memBuf, c - '0', FOUR_BIT); else if (c >= 'A' && c <= 'Z') encode(memBuf, c - 'A' + 10, FOUR_BIT); else if (c >= 'a' && c <= 'z') encode(memBuf, c - 'a' + 10, FOUR_BIT); else { printf("encodeSemiConstrainedHexString\n"); exit(EXIT_FAILURE); } } } char *decodeSemiConstrainedHexString(packedDecode *memBuf, char *s) { int len, i; char *baseptr; len = decodeGeneralLengthDeterminant(memBuf); #ifdef DEBUG puts("decodeSemiConstrainedHexString"); printf("len = %d\n", len); #endif baseptr = s; for (i = 0; i < len; i++) *s++ = hexchar[decode(memBuf, FOUR_BIT)]; *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } ////// void encodeFixedLengthNumericString(packedEncode *memBuf, char *s, int len) { encodeFixedLengthHexString(memBuf, s, len); } char *decodeFixedLengthNumericString(packedDecode *memBuf, char *s, int len) { return decodeFixedLengthHexString(memBuf, s, len); } void encodeConstrainedNumericString(packedEncode *memBuf, char *s, int lb, int ub) { encodeConstrainedHexString(memBuf, s, lb, ub); } char *decodeConstrainedNumericString(packedDecode *memBuf, char *s, int lb, int ub) { return decodeConstrainedHexString(memBuf, s, lb, ub); } void encodeSemiConstrainedNumericString(packedEncode *memBuf, char *s) { encodeSemiConstrainedHexString(memBuf, s); } char *decodeSemiConstrainedNumericString(packedDecode *memBuf, char *s) { return decodeSemiConstrainedHexString(memBuf, s); } ////// void encodeFixedLengthString(packedEncode *memBuf, char *s, int len) { int i; #ifdef DEBUG puts("encodeFixedLengthString"); printf("s = %s\n", s); printf("len = %d\n", len); #endif for (i = 0; i < len; i++) { encode(memBuf, *(s+i), SEVEN_BIT); } } char *decodeFixedLengthString(packedDecode *memBuf, char *s, int len) { int i; char *baseptr; #ifdef DEBUG puts("decodeFixedLengthString"); printf("len = %d\n", len); #endif baseptr = s; for (i = 0; i < len; i++) *s++ = decode(memBuf, SEVEN_BIT); *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } void encodeConstrainedString(packedEncode *memBuf, char *s, int lb, int ub) { int bits, len, i; bits = bitcount(ub - lb + 1); len = strlen(s); /* encode length as constrained whole number */ encode(memBuf, len - lb, bits); for (i = 0; i < len; i++) { encode(memBuf, *(s+i), SEVEN_BIT); } } char *decodeConstrainedString(packedDecode *memBuf, char *s, int lb, int ub) { int len, i; char *baseptr; /* get length as constrained whole number */ len = decode(memBuf, bitcount(ub - lb + 1)) + lb; #ifdef DEBUG puts("decodeConstrainedString"); printf("len = %d\n", len); #endif baseptr = s; for (i = 0; i < len; i++) *s++ = decode(memBuf, SEVEN_BIT); *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } void encodeSemiConstrainedString(packedEncode *memBuf, char *s) { int len, i; len = strlen(s); #ifdef DEBUG puts("encodeSemiConstrainedString"); printf("s = %s\n", s); #endif /* first need to encode a length value of the string */ encodeGeneralLengthDeterminant(memBuf, len); #ifdef DEBUG printf("len = %d\n", len); #endif for (i = 0; i < len; i++) { encode(memBuf, *(s+i), SEVEN_BIT); } } char *decodeSemiConstrainedString(packedDecode *memBuf, char *s) { int len, i; char *baseptr; len = decodeGeneralLengthDeterminant(memBuf); #ifdef DEBUG puts("decodeSemiConstrainedString"); printf("len = %d\n", len); #endif baseptr = s; for (i = 0; i < len; i++) *s++ = decode(memBuf, SEVEN_BIT); *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } /* octetString */ void encodeFixedLengthOctetString(packedEncode *memBuf, char *s, int len) { int i; #ifdef DEBUG puts("encodeFixedLengthOctetString"); printf("s = %s\n", s); printf("len = %d\n", len); #endif for (i = 0; i < len; i++) { encode(memBuf, *(s+i), EIGHT_BIT); } } char *decodeFixedLengthOctetString(packedDecode *memBuf, char *s, int len) { int i; char *baseptr; #ifdef DEBUG puts("decodeFixedLengthOctetString"); printf("len = %d\n", len); #endif baseptr = s; for (i = 0; i < len; i++) *s++ = decode(memBuf, EIGHT_BIT); *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } void encodeConstrainedOctetString(packedEncode *memBuf, char *s, int lb, int ub) { int bits, len, i; bits = bitcount(ub - lb + 1); len = strlen(s); /* encode length as constrained whole number */ encode(memBuf, len - lb, bits); for (i = 0; i < len; i++) { encode(memBuf, *(s+i), EIGHT_BIT); } } char *decodeConstrainedOctetString(packedDecode *memBuf, char *s, int lb, int ub) { int len, i; char *baseptr; /* get length as constrained whole number */ len = decode(memBuf, bitcount(ub - lb + 1)) + lb; #ifdef DEBUG puts("decodeConstrainedOctetString"); printf("len = %d\n", len); #endif baseptr = s; for (i = 0; i < len; i++) *s++ = decode(memBuf, EIGHT_BIT); *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } void encodeSemiConstrainedOctetString(packedEncode *memBuf, char *s) { int len, i; len = strlen(s); #ifdef DEBUG puts("encodeSemiConstrainedOctetString"); printf("s = %s\n", s); #endif /* first need to encode a length value of the string */ encodeGeneralLengthDeterminant(memBuf, len); #ifdef DEBUG printf("len = %d\n", len); #endif for (i = 0; i < len; i++) { encode(memBuf, *(s+i), EIGHT_BIT); } } char *decodeSemiConstrainedOctetString(packedDecode *memBuf, char *s) { int len, i; char *baseptr; len = decodeGeneralLengthDeterminant(memBuf); #ifdef DEBUG puts("decodeSemiConstrainedOctetString"); printf("len = %d\n", len); #endif baseptr = s; for (i = 0; i < len; i++) *s++ = decode(memBuf, EIGHT_BIT); *s = '\0'; s = baseptr; #ifdef DEBUG printf("s = %s\n", s); #endif return s; } /* not sure why I am masking out 0's? */ void encodeUnconstrainedInteger(packedEncode *memBuf, signed long int n) { int nbytes; if (n >= SCHAR_MIN && n <= SCHAR_MAX) { nbytes = 1; n = n & UCHAR_MAX; } else if (n >= SHRT_MIN && n <= SHRT_MAX) { nbytes = 2; n = n & USHRT_MAX; } else if (n >= INT_MIN && n <= INT_MAX) { nbytes = 4; } else perror("encodeUnconstrainedInteger"); encodeGeneralLengthDeterminant(memBuf, nbytes); encode(memBuf, n, (nbytes * CHAR_BIT)); } signed long int decodeUnconstrainedInteger(packedDecode *memBuf) { int nbytes; signed long int n; nbytes = decodeGeneralLengthDeterminant(memBuf); if (nbytes == 1) { n = (signed char)decode(memBuf, nbytes * CHAR_BIT); } else if (nbytes == 2) { n = (signed short)decode(memBuf, nbytes * CHAR_BIT); } else if (nbytes == 4) { n = decode(memBuf, nbytes * CHAR_BIT); } else perror("decodeUnconstrainedInteger"); return n; } /* not sure why I am masking out 0's? */ void encodeSignedSemiConstrainedInteger(packedEncode *memBuf, signed long int n, int lb) { int nbytes; n = n - lb; if (n >= SCHAR_MIN && n <= SCHAR_MAX) { nbytes = 1; n = n & UCHAR_MAX; } else if (n >= SHRT_MIN && n <= SHRT_MAX) { nbytes = 2; n = n & USHRT_MAX; } else if (n >= INT_MIN && n <= INT_MAX) { nbytes = 4; } else perror("encodeSignedSemiConstrainedInteger"); encodeGeneralLengthDeterminant(memBuf, nbytes); encode(memBuf, n, (nbytes * CHAR_BIT)); } signed long int decodeSignedSemiConstrainedInteger(packedDecode *memBuf, int lb) { int nbytes; signed long int n; nbytes = decodeGeneralLengthDeterminant(memBuf); if (nbytes == 1) { n = (signed char)decode(memBuf, nbytes * CHAR_BIT); } else if (nbytes == 2) { n = (signed short)decode(memBuf, nbytes * CHAR_BIT); } else if (nbytes == 4) { n = decode(memBuf, nbytes * CHAR_BIT); } else perror("decodeSignedSemiConstrainedInteger"); return n + lb; } void encodeUnsignedSemiConstrainedInteger(packedEncode *memBuf, unsigned long int n, unsigned lb) { int nbytes; n = n - lb; if (n <= UCHAR_MAX) { nbytes = 1; } else if (n <= USHRT_MAX) { nbytes = 2; } else if (n <= UINT_MAX) { nbytes = 4; } else perror("encodeUnsignedSemiConstrainedInteger"); encodeGeneralLengthDeterminant(memBuf, nbytes); encode(memBuf, n, (nbytes * CHAR_BIT)); } unsigned long int decodeUnsignedSemiConstrainedInteger(packedDecode *memBuf, unsigned lb) { int nbytes; unsigned long int n; nbytes = decodeGeneralLengthDeterminant(memBuf); if (nbytes == 1) { n = (unsigned char)decode(memBuf, nbytes * CHAR_BIT); } else if (nbytes == 2) { n = (unsigned short)decode(memBuf, nbytes * CHAR_BIT); } else if (nbytes == 4) { n = decode(memBuf, nbytes * CHAR_BIT); } else perror("decodeUnsignedSemiConstrainedInteger"); return n + lb; } void encodeUnsignedConstrainedInteger(packedEncode *memBuf, unsigned long int n, unsigned lb, unsigned ub) { int bits; bits = bitcount(ub - lb + 1); encode(memBuf, (n - lb), bits); } unsigned long int decodeUnsignedConstrainedInteger(packedDecode *memBuf, unsigned lb, unsigned ub) { return (decode(memBuf, bitcount(ub - lb + 1)) + lb); } void encodeSignedConstrainedInteger(packedEncode *memBuf, signed long int n, int lb, int ub) { int bits; bits = bitcount(ub - lb + 1); encode(memBuf, (n - lb), bits); } signed long int decodeSignedConstrainedInteger(packedDecode *memBuf, int lb, int ub) { return (decode(memBuf, bitcount(ub - lb + 1)) + lb); } void encodeEnumerated(packedEncode *memBuf, unsigned long int n, unsigned len) { /* ub = length - 1 */ encodeUnsignedConstrainedInteger(memBuf, n, 0, len-1); } unsigned long int decodeEnumerated(packedDecode *memBuf, unsigned len) { return (decodeUnsignedConstrainedInteger(memBuf, 0, len-1)); } void encodeSetBitmap(packedEncode *memBuf, char *bitmap, int len) { encodeFixedLengthBitString(memBuf, bitmap, len); } char *decodeSetBitmap(packedDecode *memBuf, char *s, int len) { return (decodeFixedLengthBitString(memBuf, s, len)); } void encodeChoiceIndex(packedEncode *memBuf, unsigned long int n, unsigned len) { encodeUnsignedConstrainedInteger(memBuf, n, 1, len); } unsigned long int decodeChoiceIndex(packedDecode *memBuf, unsigned len) { return (decodeUnsignedConstrainedInteger(memBuf, 1, len)); } void encodeSequenceOfLength(packedEncode *memBuf, int len) { encodeGeneralLengthDeterminant(memBuf, len); } int decodeSequenceOfLength(packedDecode *memBuf) { return (decodeGeneralLengthDeterminant(memBuf)); }