LCOV - code coverage report
Current view: top level - asn1 - a_mbstr.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 86 168 51.2 %
Date: 2014-08-02 Functions: 8 11 72.7 %
Branches: 58 100 58.0 %

           Branch data     Line data    Source code
       1                 :            : /* a_mbstr.c */
       2                 :            : /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
       3                 :            :  * project 1999.
       4                 :            :  */
       5                 :            : /* ====================================================================
       6                 :            :  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
       7                 :            :  *
       8                 :            :  * Redistribution and use in source and binary forms, with or without
       9                 :            :  * modification, are permitted provided that the following conditions
      10                 :            :  * are met:
      11                 :            :  *
      12                 :            :  * 1. Redistributions of source code must retain the above copyright
      13                 :            :  *    notice, this list of conditions and the following disclaimer. 
      14                 :            :  *
      15                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      16                 :            :  *    notice, this list of conditions and the following disclaimer in
      17                 :            :  *    the documentation and/or other materials provided with the
      18                 :            :  *    distribution.
      19                 :            :  *
      20                 :            :  * 3. All advertising materials mentioning features or use of this
      21                 :            :  *    software must display the following acknowledgment:
      22                 :            :  *    "This product includes software developed by the OpenSSL Project
      23                 :            :  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
      24                 :            :  *
      25                 :            :  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
      26                 :            :  *    endorse or promote products derived from this software without
      27                 :            :  *    prior written permission. For written permission, please contact
      28                 :            :  *    licensing@OpenSSL.org.
      29                 :            :  *
      30                 :            :  * 5. Products derived from this software may not be called "OpenSSL"
      31                 :            :  *    nor may "OpenSSL" appear in their names without prior written
      32                 :            :  *    permission of the OpenSSL Project.
      33                 :            :  *
      34                 :            :  * 6. Redistributions of any form whatsoever must retain the following
      35                 :            :  *    acknowledgment:
      36                 :            :  *    "This product includes software developed by the OpenSSL Project
      37                 :            :  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
      38                 :            :  *
      39                 :            :  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
      40                 :            :  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      41                 :            :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      42                 :            :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
      43                 :            :  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      44                 :            :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      45                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      46                 :            :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      47                 :            :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      48                 :            :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      49                 :            :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
      50                 :            :  * OF THE POSSIBILITY OF SUCH DAMAGE.
      51                 :            :  * ====================================================================
      52                 :            :  *
      53                 :            :  * This product includes cryptographic software written by Eric Young
      54                 :            :  * (eay@cryptsoft.com).  This product includes software written by Tim
      55                 :            :  * Hudson (tjh@cryptsoft.com).
      56                 :            :  *
      57                 :            :  */
      58                 :            : 
      59                 :            : #include <stdio.h>
      60                 :            : #include <ctype.h>
      61                 :            : #include "cryptlib.h"
      62                 :            : #include <openssl/asn1.h>
      63                 :            : 
      64                 :            : static int traverse_string(const unsigned char *p, int len, int inform,
      65                 :            :                  int (*rfunc)(unsigned long value, void *in), void *arg);
      66                 :            : static int in_utf8(unsigned long value, void *arg);
      67                 :            : static int out_utf8(unsigned long value, void *arg);
      68                 :            : static int type_str(unsigned long value, void *arg);
      69                 :            : static int cpy_asc(unsigned long value, void *arg);
      70                 :            : static int cpy_bmp(unsigned long value, void *arg);
      71                 :            : static int cpy_univ(unsigned long value, void *arg);
      72                 :            : static int cpy_utf8(unsigned long value, void *arg);
      73                 :            : static int is_printable(unsigned long value);
      74                 :            : 
      75                 :            : /* These functions take a string in UTF8, ASCII or multibyte form and
      76                 :            :  * a mask of permissible ASN1 string types. It then works out the minimal
      77                 :            :  * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
      78                 :            :  * and creates a string of the correct type with the supplied data.
      79                 :            :  * Yes this is horrible: it has to be :-(
      80                 :            :  * The 'ncopy' form checks minimum and maximum size limits too.
      81                 :            :  */
      82                 :            : 
      83                 :      88862 : int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
      84                 :            :                                         int inform, unsigned long mask)
      85                 :            : {
      86                 :      88862 :         return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
      87                 :            : }
      88                 :            : 
      89                 :      89510 : int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
      90                 :            :                                         int inform, unsigned long mask, 
      91                 :            :                                         long minsize, long maxsize)
      92                 :            : {
      93                 :            :         int str_type;
      94                 :            :         int ret;
      95                 :            :         char free_out;
      96                 :      89510 :         int outform, outlen = 0;
      97                 :            :         ASN1_STRING *dest;
      98                 :            :         unsigned char *p;
      99                 :            :         int nchar;
     100                 :            :         char strbuf[32];
     101                 :      89510 :         int (*cpyfunc)(unsigned long,void *) = NULL;
     102         [ +  + ]:      89510 :         if(len == -1) len = strlen((const char *)in);
     103         [ -  + ]:      89510 :         if(!mask) mask = DIRSTRING_TYPE;
     104                 :            : 
     105                 :            :         /* First do a string check and work out the number of characters */
     106   [ -  -  +  +  :      89510 :         switch(inform) {
                      - ]
     107                 :            : 
     108                 :            :                 case MBSTRING_BMP:
     109         [ #  # ]:          0 :                 if(len & 1) {
     110                 :          0 :                         ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
     111                 :            :                                          ASN1_R_INVALID_BMPSTRING_LENGTH);
     112                 :          0 :                         return -1;
     113                 :            :                 }
     114                 :          0 :                 nchar = len >> 1;
     115                 :          0 :                 break;
     116                 :            : 
     117                 :            :                 case MBSTRING_UNIV:
     118         [ #  # ]:          0 :                 if(len & 3) {
     119                 :          0 :                         ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
     120                 :            :                                          ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
     121                 :          0 :                         return -1;
     122                 :            :                 }
     123                 :          0 :                 nchar = len >> 2;
     124                 :          0 :                 break;
     125                 :            : 
     126                 :            :                 case MBSTRING_UTF8:
     127                 :      60549 :                 nchar = 0;
     128                 :            :                 /* This counts the characters and does utf8 syntax checking */
     129                 :      60549 :                 ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
     130         [ -  + ]:      60549 :                 if(ret < 0) {
     131                 :          0 :                         ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
     132                 :            :                                                  ASN1_R_INVALID_UTF8STRING);
     133                 :          0 :                         return -1;
     134                 :            :                 }
     135                 :            :                 break;
     136                 :            : 
     137                 :            :                 case MBSTRING_ASC:
     138                 :      28961 :                 nchar = len;
     139                 :      28961 :                 break;
     140                 :            : 
     141                 :            :                 default:
     142                 :          0 :                 ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_UNKNOWN_FORMAT);
     143                 :          0 :                 return -1;
     144                 :            :         }
     145                 :            : 
     146 [ +  + ][ -  + ]:      89510 :         if((minsize > 0) && (nchar < minsize)) {
     147                 :          0 :                 ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_SHORT);
     148                 :          0 :                 BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
     149                 :          0 :                 ERR_add_error_data(2, "minsize=", strbuf);
     150                 :          0 :                 return -1;
     151                 :            :         }
     152                 :            : 
     153 [ +  + ][ -  + ]:      89510 :         if((maxsize > 0) && (nchar > maxsize)) {
     154                 :          0 :                 ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG);
     155                 :          0 :                 BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
     156                 :          0 :                 ERR_add_error_data(2, "maxsize=", strbuf);
     157                 :          0 :                 return -1;
     158                 :            :         }
     159                 :            : 
     160                 :            :         /* Now work out minimal type (if any) */
     161         [ -  + ]:      89510 :         if(traverse_string(in, len, inform, type_str, &mask) < 0) {
     162                 :          0 :                 ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_ILLEGAL_CHARACTERS);
     163                 :          0 :                 return -1;
     164                 :            :         }
     165                 :            : 
     166                 :            : 
     167                 :            :         /* Now work out output format and string type */
     168                 :      89510 :         outform = MBSTRING_ASC;
     169         [ +  + ]:      89510 :         if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING;
     170         [ +  + ]:      89488 :         else if(mask & B_ASN1_IA5STRING) str_type = V_ASN1_IA5STRING;
     171         [ +  - ]:      89186 :         else if(mask & B_ASN1_T61STRING) str_type = V_ASN1_T61STRING;
     172         [ +  - ]:      89186 :         else if(mask & B_ASN1_BMPSTRING) {
     173                 :            :                 str_type = V_ASN1_BMPSTRING;
     174                 :            :                 outform = MBSTRING_BMP;
     175         [ +  - ]:      89186 :         } else if(mask & B_ASN1_UNIVERSALSTRING) {
     176                 :            :                 str_type = V_ASN1_UNIVERSALSTRING;
     177                 :            :                 outform = MBSTRING_UNIV;
     178                 :            :         } else {
     179                 :      89186 :                 str_type = V_ASN1_UTF8STRING;
     180                 :      89186 :                 outform = MBSTRING_UTF8;
     181                 :            :         }
     182         [ +  - ]:      89510 :         if(!out) return str_type;
     183         [ +  - ]:      89510 :         if(*out) {
     184                 :      89510 :                 free_out = 0;
     185                 :      89510 :                 dest = *out;
     186         [ -  + ]:      89510 :                 if(dest->data) {
     187                 :          0 :                         dest->length = 0;
     188                 :          0 :                         OPENSSL_free(dest->data);
     189                 :          0 :                         dest->data = NULL;
     190                 :            :                 }
     191                 :      89510 :                 dest->type = str_type;
     192                 :            :         } else {
     193                 :          0 :                 free_out = 1;
     194                 :          0 :                 dest = ASN1_STRING_type_new(str_type);
     195         [ #  # ]:          0 :                 if(!dest) {
     196                 :          0 :                         ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
     197                 :            :                                                         ERR_R_MALLOC_FAILURE);
     198                 :          0 :                         return -1;
     199                 :            :                 }
     200                 :          0 :                 *out = dest;
     201                 :            :         }
     202                 :            :         /* If both the same type just copy across */
     203         [ +  + ]:      89510 :         if(inform == outform) {
     204         [ -  + ]:      60873 :                 if(!ASN1_STRING_set(dest, in, len)) {
     205                 :          0 :                         ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,ERR_R_MALLOC_FAILURE);
     206                 :          0 :                         return -1;
     207                 :            :                 }
     208                 :            :                 return str_type;
     209                 :            :         } 
     210                 :            : 
     211                 :            :         /* Work out how much space the destination will need */
     212   [ -  -  -  +  :      28637 :         switch(outform) {
                      - ]
     213                 :            :                 case MBSTRING_ASC:
     214                 :          0 :                 outlen = nchar;
     215                 :          0 :                 cpyfunc = cpy_asc;
     216                 :          0 :                 break;
     217                 :            : 
     218                 :            :                 case MBSTRING_BMP:
     219                 :          0 :                 outlen = nchar << 1;
     220                 :          0 :                 cpyfunc = cpy_bmp;
     221                 :          0 :                 break;
     222                 :            : 
     223                 :            :                 case MBSTRING_UNIV:
     224                 :          0 :                 outlen = nchar << 2;
     225                 :          0 :                 cpyfunc = cpy_univ;
     226                 :          0 :                 break;
     227                 :            : 
     228                 :            :                 case MBSTRING_UTF8:
     229                 :      28637 :                 outlen = 0;
     230                 :      28637 :                 traverse_string(in, len, inform, out_utf8, &outlen);
     231                 :      28637 :                 cpyfunc = cpy_utf8;
     232                 :      28637 :                 break;
     233                 :            :         }
     234         [ -  + ]:      28637 :         if(!(p = OPENSSL_malloc(outlen + 1))) {
     235         [ #  # ]:          0 :                 if(free_out) ASN1_STRING_free(dest);
     236                 :          0 :                 ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,ERR_R_MALLOC_FAILURE);
     237                 :          0 :                 return -1;
     238                 :            :         }
     239                 :      28637 :         dest->length = outlen;
     240                 :      28637 :         dest->data = p;
     241                 :      28637 :         p[outlen] = 0;
     242                 :      28637 :         traverse_string(in, len, inform, cpyfunc, &p);
     243                 :      28637 :         return str_type;        
     244                 :            : }
     245                 :            : 
     246                 :            : /* This function traverses a string and passes the value of each character
     247                 :            :  * to an optional function along with a void * argument.
     248                 :            :  */
     249                 :            : 
     250                 :     207333 : static int traverse_string(const unsigned char *p, int len, int inform,
     251                 :            :                  int (*rfunc)(unsigned long value, void *in), void *arg)
     252                 :            : {
     253                 :            :         unsigned long value;
     254                 :            :         int ret;
     255         [ +  + ]:    2173112 :         while(len) {
     256         [ +  + ]:    1965779 :                 if(inform == MBSTRING_ASC) {
     257                 :     677605 :                         value = *p++;
     258                 :     677605 :                         len--;
     259         [ -  + ]:    1288174 :                 } else if(inform == MBSTRING_BMP) {
     260                 :          0 :                         value = *p++ << 8;
     261                 :          0 :                         value |= *p++;
     262                 :          0 :                         len -= 2;
     263         [ -  + ]:    1288174 :                 } else if(inform == MBSTRING_UNIV) {
     264                 :          0 :                         value = ((unsigned long)*p++) << 24;
     265                 :          0 :                         value |= ((unsigned long)*p++) << 16;
     266                 :          0 :                         value |= *p++ << 8;
     267                 :          0 :                         value |= *p++;
     268                 :          0 :                         len -= 4;
     269                 :            :                 } else {
     270                 :    1288174 :                         ret = UTF8_getc(p, len, &value);
     271         [ +  - ]:    1288174 :                         if(ret < 0) return -1;
     272                 :    1288174 :                         len -= ret;
     273                 :    1288174 :                         p += ret;
     274                 :            :                 }
     275         [ +  - ]:    1965779 :                 if(rfunc) {
     276                 :    1965779 :                         ret = rfunc(value, arg);
     277         [ +  - ]:    1965779 :                         if(ret <= 0) return ret;
     278                 :            :                 }
     279                 :            :         }
     280                 :            :         return 1;
     281                 :            : }
     282                 :            : 
     283                 :            : /* Various utility functions for traverse_string */
     284                 :            : 
     285                 :            : /* Just count number of characters */
     286                 :            : 
     287                 :     644087 : static int in_utf8(unsigned long value, void *arg)
     288                 :            : {
     289                 :            :         int *nchar;
     290                 :     644087 :         nchar = arg;
     291                 :     644087 :         (*nchar)++;
     292                 :     644087 :         return 1;
     293                 :            : }
     294                 :            : 
     295                 :            : /* Determine size of output as a UTF8 String */
     296                 :            : 
     297                 :     224614 : static int out_utf8(unsigned long value, void *arg)
     298                 :            : {
     299                 :            :         int *outlen;
     300                 :     224614 :         outlen = arg;
     301                 :     224614 :         *outlen += UTF8_putc(NULL, -1, value);
     302                 :     224614 :         return 1;
     303                 :            : }
     304                 :            : 
     305                 :            : /* Determine the "type" of a string: check each character against a
     306                 :            :  * supplied "mask".
     307                 :            :  */
     308                 :            : 
     309                 :     872464 : static int type_str(unsigned long value, void *arg)
     310                 :            : {
     311                 :            :         unsigned long types;
     312                 :     872464 :         types = *((unsigned long *)arg);
     313 [ +  + ][ -  + ]:     872464 :         if((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
     314                 :          0 :                                         types &= ~B_ASN1_PRINTABLESTRING;
     315 [ +  + ][ -  + ]:     872464 :         if((types & B_ASN1_IA5STRING) && (value > 127))
     316                 :          0 :                                         types &= ~B_ASN1_IA5STRING;
     317 [ +  + ][ -  + ]:     872464 :         if((types & B_ASN1_T61STRING) && (value > 0xff))
     318                 :          0 :                                         types &= ~B_ASN1_T61STRING;
     319 [ -  + ][ #  # ]:     872464 :         if((types & B_ASN1_BMPSTRING) && (value > 0xffff))
     320                 :          0 :                                         types &= ~B_ASN1_BMPSTRING;
     321         [ +  - ]:     872464 :         if(!types) return -1;
     322                 :     872464 :         *((unsigned long *)arg) = types;
     323                 :     872464 :         return 1;
     324                 :            : }
     325                 :            : 
     326                 :            : /* Copy one byte per character ASCII like strings */
     327                 :            : 
     328                 :          0 : static int cpy_asc(unsigned long value, void *arg)
     329                 :            : {
     330                 :            :         unsigned char **p, *q;
     331                 :          0 :         p = arg;
     332                 :          0 :         q = *p;
     333                 :          0 :         *q = (unsigned char) value;
     334                 :          0 :         (*p)++;
     335                 :          0 :         return 1;
     336                 :            : }
     337                 :            : 
     338                 :            : /* Copy two byte per character BMPStrings */
     339                 :            : 
     340                 :          0 : static int cpy_bmp(unsigned long value, void *arg)
     341                 :            : {
     342                 :            :         unsigned char **p, *q;
     343                 :          0 :         p = arg;
     344                 :          0 :         q = *p;
     345                 :          0 :         *q++ = (unsigned char) ((value >> 8) & 0xff);
     346                 :          0 :         *q = (unsigned char) (value & 0xff);
     347                 :          0 :         *p += 2;
     348                 :          0 :         return 1;
     349                 :            : }
     350                 :            : 
     351                 :            : /* Copy four byte per character UniversalStrings */
     352                 :            : 
     353                 :          0 : static int cpy_univ(unsigned long value, void *arg)
     354                 :            : {
     355                 :            :         unsigned char **p, *q;
     356                 :          0 :         p = arg;
     357                 :          0 :         q = *p;
     358                 :          0 :         *q++ = (unsigned char) ((value >> 24) & 0xff);
     359                 :          0 :         *q++ = (unsigned char) ((value >> 16) & 0xff);
     360                 :          0 :         *q++ = (unsigned char) ((value >> 8) & 0xff);
     361                 :          0 :         *q = (unsigned char) (value & 0xff);
     362                 :          0 :         *p += 4;
     363                 :          0 :         return 1;
     364                 :            : }
     365                 :            : 
     366                 :            : /* Copy to a UTF8String */
     367                 :            : 
     368                 :     224614 : static int cpy_utf8(unsigned long value, void *arg)
     369                 :            : {
     370                 :            :         unsigned char **p;
     371                 :            :         int ret;
     372                 :     224614 :         p = arg;
     373                 :            :         /* We already know there is enough room so pass 0xff as the length */
     374                 :     224614 :         ret = UTF8_putc(*p, 0xff, value);
     375                 :     224614 :         *p += ret;
     376                 :     224614 :         return 1;
     377                 :            : }
     378                 :            : 
     379                 :            : /* Return 1 if the character is permitted in a PrintableString */
     380                 :        106 : static int is_printable(unsigned long value)
     381                 :            : {
     382                 :            :         int ch;
     383         [ +  - ]:        106 :         if(value > 0x7f) return 0;
     384                 :        106 :         ch = (int) value;
     385                 :            :         /* Note: we can't use 'isalnum' because certain accented 
     386                 :            :          * characters may count as alphanumeric in some environments.
     387                 :            :          */
     388                 :            : #ifndef CHARSET_EBCDIC
     389         [ +  + ]:        106 :         if((ch >= 'a') && (ch <= 'z')) return 1;
     390         [ +  + ]:         52 :         if((ch >= 'A') && (ch <= 'Z')) return 1;
     391         [ +  + ]:         12 :         if((ch >= '0') && (ch <= '9')) return 1;
     392 [ +  + ][ -  + ]:          9 :         if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1;
     393                 :            : #else /*CHARSET_EBCDIC*/
     394                 :            :         if((ch >= os_toascii['a']) && (ch <= os_toascii['z'])) return 1;
     395                 :            :         if((ch >= os_toascii['A']) && (ch <= os_toascii['Z'])) return 1;
     396                 :            :         if((ch >= os_toascii['0']) && (ch <= os_toascii['9'])) return 1;
     397                 :            :         if ((ch == os_toascii[' ']) || strchr("'()+,-./:=?", os_toebcdic[ch])) return 1;
     398                 :            : #endif /*CHARSET_EBCDIC*/
     399                 :          0 :         return 0;
     400                 :            : }

Generated by: LCOV version 1.9