LCOV - code coverage report
Current view: top level - third_party/openssl/crypto/asn1 - a_mbstr.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 69 154 44.8 %
Date: 2015-10-10 Functions: 7 11 63.6 %

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

Generated by: LCOV version 1.10