From e90b059603a1018abd548a9446a59778c121e4ad Mon Sep 17 00:00:00 2001 From: Simon Josefsson Date: Wed, 26 Mar 2003 13:57:22 +0000 Subject: [PATCH] Upstream sync. --- asn1/ChangeLog | 27 ----- asn1/NEWS | 15 +++ asn1/configure.in | 6 +- asn1/doc/asn1.tex | 2 +- asn1/lib/ASN1.c | 137 ++++++++++++--------- asn1/lib/coding.c | 258 ++++++++++++++++++++++++++++++---------- asn1/lib/decoding.c | 16 +-- asn1/lib/element.c | 119 +++++++++++------- asn1/lib/errors.c | 1 + asn1/lib/errors_int.h | 9 +- asn1/lib/int.h | 2 + asn1/lib/libtasn1.h | 21 ++-- asn1/lib/parser_aux.c | 142 +++++++++++++++++++++- asn1/lib/structure.c | 22 ++-- asn1/src/CertificateExample.c | 16 ++- asn1/src/CrlExample.c | 11 +- asn1/src/asn1Coding.c | 1 + asn1/tests/Test_parser.asn | 8 ++ asn1/tests/Test_parser.c | 10 ++ asn1/tests/Test_tree.asn | 22 +++- asn1/tests/Test_tree.c | 161 ++++++++++++++++++++----- asn1/tests/Test_tree_asn1_tab.c | 115 +++++++++++++++++- crypto/AUTHORS | 4 +- crypto/ChangeLog | 13 ++ crypto/NEWS | 11 ++ crypto/THANKS | 1 + crypto/TODO | 6 +- crypto/cipher/ChangeLog | 111 +++++++++++++++++ crypto/cipher/arcfour.c | 20 +--- crypto/cipher/blowfish.c | 20 +--- crypto/cipher/cast5.c | 20 +--- crypto/cipher/cipher.c | 65 ++++++++-- crypto/cipher/des.c | 36 ++---- crypto/cipher/dynload.c | 8 +- crypto/cipher/dynload.h | 4 +- crypto/cipher/elgamal.c | 4 +- crypto/cipher/elgamal.h | 4 +- crypto/cipher/md.c | 31 ++--- crypto/cipher/md4.c | 19 +-- crypto/cipher/md5.c | 20 +--- crypto/cipher/primegen.c | 201 ++++++++++++++++--------------- crypto/cipher/pubkey.c | 74 ++++++++---- crypto/cipher/random.c | 15 +-- crypto/cipher/rijndael.c | 21 +--- crypto/cipher/rmd160.c | 20 +--- crypto/cipher/rsa.c | 190 +++++++++++++++++++++++++---- crypto/cipher/rsa.h | 4 +- crypto/cipher/sha1.c | 20 +--- crypto/cipher/sha256.c | 18 +-- crypto/cipher/tiger.c | 20 +--- crypto/cipher/twofish.c | 19 +-- crypto/doc/ChangeLog | 8 ++ crypto/doc/gcrypt.texi | 69 ++++++++++- crypto/scripts/ChangeLog | 5 + crypto/scripts/autogen.sh | 19 +-- crypto/src/ChangeLog | 59 +++++++++ crypto/src/cipher.h | 2 + crypto/src/g10lib.h | 23 +++- crypto/src/gcrypt.h | 146 +++++++++++++---------- crypto/src/global.c | 11 +- crypto/src/misc.c | 19 ++- crypto/src/secmem.c | 13 +- crypto/src/secmem.h | 9 +- crypto/src/sexp.c | 9 +- crypto/tests/ChangeLog | 22 ++++ crypto/tests/Makefile.am | 9 +- crypto/tests/basic.c | 101 +++++++++++++--- crypto/tests/keygen.c | 16 ++- crypto/tests/pubkey.c | 148 +++++++++++++++++++++++ 69 files changed, 2011 insertions(+), 797 deletions(-) rewrite asn1/ChangeLog (100%) create mode 100644 crypto/tests/pubkey.c diff --git a/asn1/ChangeLog b/asn1/ChangeLog dissimilarity index 100% index f1a00e89..e69de29b 100644 --- a/asn1/ChangeLog +++ b/asn1/ChangeLog @@ -1,27 +0,0 @@ -2002-11-29 Simon Josefsson - - * lib/element.c (_asn1_convert_integer): Align integer correctly - (prevents bus errors on e.g. Solaris). - -2002-09-08 Simon Josefsson - - * lib/structure.c (_asn1_copy_structure3, asn1_print_structure): - Support GeneralString. - - * lib/int.h (TYPE_GENERALSTRING): Support GeneralString. - - * lib/element.c (asn1_write_value, asn1_write_value) - (asn1_read_value): Support GeneralString. - - * lib/der.h (TAG_GENERALSTRING): Support GeneralString. - - * lib/decoding.c (_asn1_extract_tag_der, asn1_der_decoding) - (asn1_der_decoding_startEnd): Support GeneralString. - - * lib/coding.c (_asn1_complete_explicit_tag): Support nested tags. - (_asn1_insert_tag_der, asn1_der_coding): Support GeneralString. - - * lib/ASN1.y: Support GeneralString. - - * doc/Makefile.am (asn1.html): Depend on asn1.ps. - diff --git a/asn1/NEWS b/asn1/NEWS index 39ebade2..be38cd27 100644 --- a/asn1/NEWS +++ b/asn1/NEWS @@ -1,3 +1,18 @@ +Version 0.2.4 +- Bug fix in asn1_der_coding with NULL parameter +- Manage DEFAULT option with OBJECT IDENTIFIER + +Version 0.2.3 +- Chenge asn1_find_structure_from_oid prototype +- Chenge asn1_find_structure_from_oid prototype +- Add ASN1_MEM_ALLOC_ERROR return value + +Version 0.2.2 +- Add vector length check in asn1_der_coding function +- Add vector length check in asn1_der_coding function +- Add vector length check in asn1_read_value function +- Add asn1_check_version function + Version 0.2.1 - Add asn1_find_structure_from_oid function - Add asn1_read_tag function diff --git a/asn1/configure.in b/asn1/configure.in index e0e2e2e5..261c3e9a 100644 --- a/asn1/configure.in +++ b/asn1/configure.in @@ -12,7 +12,7 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os") dnl libtasn1 Version ASN1_MAJOR_VERSION=0 ASN1_MINOR_VERSION=2 -ASN1_MICRO_VERSION=1 +ASN1_MICRO_VERSION=4 ASN1_VERSION=$ASN1_MAJOR_VERSION.$ASN1_MINOR_VERSION.$ASN1_MICRO_VERSION AC_DEFINE_UNQUOTED(ASN1_VERSION, "$ASN1_VERSION") @@ -21,9 +21,9 @@ AM_INIT_AUTOMAKE(libtasn1, $ASN1_VERSION) AM_CONFIG_HEADER(config.h) dnl This is the library version -ASN1_MOST_RECENT_INTERFACE=1 +ASN1_MOST_RECENT_INTERFACE=2 ASN1_CURRENT_INTERFACE_IMPLEMENTATION_NUMBER=$ASN1_MICRO_VERSION -ASN1_OLDEST_INTERFACE=1 +ASN1_OLDEST_INTERFACE=2 AC_SUBST(ASN1_MAJOR_VERSION) diff --git a/asn1/doc/asn1.tex b/asn1/doc/asn1.tex index 937d453c..b5ac45e6 100644 --- a/asn1/doc/asn1.tex +++ b/asn1/doc/asn1.tex @@ -39,7 +39,7 @@ chapter entitled "GNU Free Documentation License". \chapter{ASN.1 structures handling} \section{Introduction} - This document describes the version 0.2.0 of library 'libtasn1' developed + This document describes the version 0.2.4 of library 'libtasn1' developed for ASN1 (Abstract Syntax Notation One) structures management. The main features of this library are: \begin{itemize} diff --git a/asn1/lib/ASN1.c b/asn1/lib/ASN1.c index 8d3db959..7094adeb 100644 --- a/asn1/lib/ASN1.c +++ b/asn1/lib/ASN1.c @@ -1,5 +1,5 @@ /* A Bison parser, made from ASN1.y - by GNU bison 1.35. */ + by GNU bison 1.33. */ #define YYBISON 1 /* Identify Bison output. */ @@ -65,7 +65,7 @@ static unsigned long lineNumber; /* line number describing the parser position inside the file */ static char lastToken[MAX_NAME_SIZE+1]; /* last token find in the file to parse before the 'parse error' */ -extern char _asn1_identifierMissing[]; +char _asn1_identifierMissing[MAX_NAME_SIZE+1]; /* identifier name not found */ static const char *fileName; /* file to parse */ int _asn1_yyerror (char *); @@ -80,7 +80,6 @@ typedef union { node_asn* node; } yystype; # define YYSTYPE yystype -# define YYSTYPE_IS_TRIVIAL 1 #endif #ifndef YYDEBUG # define YYDEBUG 0 @@ -221,7 +220,7 @@ static const char *const yytname[] = "type_assig_right_tag_default", "type_assig", "type_assig_list", "sequence_def", "set_def", "choise_def", "any_def", "type_def", "constant_def", "type_constant", "type_constant_list", "definitions_id", - "explicit_implicit", 0 + "explicit_implicit", NULL }; #endif @@ -374,7 +373,7 @@ static const short yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, 69 }; /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/usr/share/bison/bison.simple" +#line 3 "/usr/local/share/bison/bison.simple" /* Skeleton output parser for bison, @@ -413,6 +412,12 @@ static const short yycheck[] = define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ +#ifdef __cplusplus +# define YYSTD(x) std::x +#else +# define YYSTD(x) x +#endif + #if ! defined (yyoverflow) || defined (YYERROR_VERBOSE) /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -435,19 +440,18 @@ static const short yycheck[] = /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # else -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t +# ifdef __cplusplus +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T std::size_t +# else +# ifdef __STDC__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif # endif -# define YYSTACK_ALLOC malloc -# define YYSTACK_FREE free +# define YYSTACK_ALLOC YYSTD (malloc) +# define YYSTACK_FREE YYSTD (free) # endif -#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ - - -#if (! defined (yyoverflow) \ - && (! defined (__cplusplus) \ - || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc @@ -474,41 +478,24 @@ union yyalloc + YYSTACK_GAP_MAX) # endif -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - register YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (0) -# endif -# endif - -/* Relocate STACK from its old location to the new one. The +/* Relocate the TYPE STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ -# define YYSTACK_RELOCATE(Stack) \ +# define YYSTACK_RELOCATE(Type, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack, Stack, yysize); \ + yymemcpy ((char *) yyptr, (char *) (Stack), \ + yysize * (YYSIZE_T) sizeof (Type)); \ Stack = &yyptr->Stack; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ + yynewbytes = yystacksize * sizeof (Type) + YYSTACK_GAP_MAX; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) -#endif +#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) @@ -518,9 +505,14 @@ union yyalloc # define YYSIZE_T size_t #endif #if ! defined (YYSIZE_T) -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t +# ifdef __cplusplus +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T std::size_t +# else +# ifdef __STDC__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif # endif #endif #if ! defined (YYSIZE_T) @@ -599,8 +591,12 @@ while (0) #if YYDEBUG # ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf +# ifdef __cplusplus +# include /* INFRINGES ON USER NAME SPACE */ +# else +# include /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYFPRINTF YYSTD (fprintf) # endif # define YYDPRINTF(Args) \ @@ -608,8 +604,10 @@ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ +/* Nonzero means print parse trace. [The following comment makes no + sense to me. Could someone clarify it? --akim] Since this is + uninitialized, it does not stop multiple parsers from coexisting. + */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) @@ -635,6 +633,33 @@ int yydebug; # define YYMAXDEPTH 10000 #endif +#if ! defined (yyoverflow) && ! defined (yymemcpy) +# if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +# define yymemcpy __builtin_memcpy +# else /* not GNU C or C++ */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +# if defined (__STDC__) || defined (__cplusplus) +yymemcpy (char *yyto, const char *yyfrom, YYSIZE_T yycount) +# else +yymemcpy (yyto, yyfrom, yycount) + char *yyto; + const char *yyfrom; + YYSIZE_T yycount; +# endif +{ + register const char *yyf = yyfrom; + register char *yyt = yyto; + register YYSIZE_T yyi = yycount; + + while (yyi-- != 0) + *yyt++ = *yyf++; +} +# endif +#endif + #ifdef YYERROR_VERBOSE # ifndef yystrlen @@ -687,7 +712,7 @@ yystpcpy (yydest, yysrc) # endif #endif -#line 315 "/usr/share/bison/bison.simple" +#line 341 "/usr/local/share/bison/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed @@ -697,13 +722,13 @@ yystpcpy (yydest, yysrc) to the proper pointer type. */ #ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) +# ifdef __cplusplus # define YYPARSE_PARAM_ARG void *YYPARSE_PARAM # define YYPARSE_PARAM_DECL -# else +# else /* !__cplusplus */ # define YYPARSE_PARAM_ARG YYPARSE_PARAM # define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; -# endif +# endif /* !__cplusplus */ #else /* !YYPARSE_PARAM */ # define YYPARSE_PARAM_ARG # define YYPARSE_PARAM_DECL @@ -877,9 +902,6 @@ yyparse (YYPARSE_PARAM_ARG) yyvs = yyvs1; } #else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyoverflowlab; -# else /* Extend the stack our own way. */ if (yystacksize >= YYMAXDEPTH) goto yyoverflowlab; @@ -893,16 +915,15 @@ yyparse (YYPARSE_PARAM_ARG) (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyoverflowlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); + YYSTACK_RELOCATE (short, yyss); + YYSTACK_RELOCATE (YYSTYPE, yyvs); # if YYLSP_NEEDED - YYSTACK_RELOCATE (yyls); + YYSTACK_RELOCATE (YYLTYPE, yyls); # endif # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } -# endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; @@ -1517,7 +1538,7 @@ case 94: break; } -#line 705 "/usr/share/bison/bison.simple" +#line 727 "/usr/local/share/bison/bison.simple" yyvsp -= yylen; diff --git a/asn1/lib/coding.c b/asn1/lib/coding.c index 3f6fdeff..ed38411a 100644 --- a/asn1/lib/coding.c +++ b/asn1/lib/coding.c @@ -32,6 +32,8 @@ #include #include "element.h" +#define MAX_TAG_LEN 16 + /******************************************************/ /* Function : _asn1_error_description_value_not_found */ /* Description: creates the ErrorDescription string */ @@ -159,18 +161,29 @@ _asn1_octet_der(const unsigned char *str,int str_len,unsigned char *der,int *der /* str: TIME null-terminated string. */ /* der: string returned. */ /* der_len: number of meanful bytes of DER */ -/* (der[0]..der[ans_len-1]). */ +/* (der[0]..der[ans_len-1]). Initially it */ +/* if must store the lenght of DER. */ /* Return: */ +/* ASN1_MEM_ERROR when DER isn't big enough */ +/* ASN1_SUCCESS otherwise */ /******************************************************/ -void +asn1_retCode _asn1_time_der(unsigned char *str,unsigned char *der,int *der_len) { int len_len; + int max_len; - if(der==NULL) return; - _asn1_length_der(strlen(str),der,&len_len); - memcpy(der+len_len,str,strlen(str)); + max_len=*der_len; + + _asn1_length_der(strlen(str),(max_len>0)?der:NULL,&len_len); + + if((len_len+(int)strlen(str))<=max_len) + memcpy(der+len_len,str,strlen(str)); *der_len=len_len+strlen(str); + + if((*der_len)>max_len) return ASN1_MEM_ERROR; + + return ASN1_SUCCESS; } @@ -217,20 +230,24 @@ _asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str) /* str: OBJECT IDENTIFIER null-terminated string. */ /* der: string returned. */ /* der_len: number of meanful bytes of DER */ -/* (der[0]..der[ans_len-1]). */ +/* (der[0]..der[ans_len-1]). Initially it */ +/* if must store the lenght of DER. */ /* Return: */ +/* ASN1_MEM_ERROR when DER isn't big enough */ +/* ASN1_SUCCESS otherwise */ /******************************************************/ -void +asn1_retCode _asn1_objectid_der(unsigned char *str,unsigned char *der,int *der_len) { - int len_len,counter,k,first; + int len_len,counter,k,first,max_len; char *temp,*n_end,*n_start; unsigned char bit7; unsigned long val,val1=0; - if(der==NULL) return; + max_len=*der_len; - temp=(char *) malloc(strlen(str)+2); + temp=(char *) _asn1_alloca(strlen(str)+2); + if(temp==NULL) return ASN1_MEM_ALLOC_ERROR; strcpy(temp, str); strcat(temp, "."); @@ -244,7 +261,8 @@ _asn1_objectid_der(unsigned char *str,unsigned char *der,int *der_len) if(counter==1) val1=val; else if(counter==2){ - der[0]=40*val1+val; + if(max_len>0) + der[0]=40*val1+val; *der_len=1; } else{ @@ -253,7 +271,8 @@ _asn1_objectid_der(unsigned char *str,unsigned char *der,int *der_len) bit7=(val>>(k*7))&0x7F; if(bit7 || first || !k){ if(k) bit7|=0x80; - der[*der_len]=bit7; + if(max_len>(*der_len)) + der[*der_len]=bit7; (*der_len)++; first=1; } @@ -264,11 +283,17 @@ _asn1_objectid_der(unsigned char *str,unsigned char *der,int *der_len) } _asn1_length_der(*der_len,NULL,&len_len); - memmove(der+len_len,der,*der_len); - _asn1_length_der(*der_len,der,&len_len); + if(max_len>=(*der_len+len_len)){ + memmove(der+len_len,der,*der_len); + _asn1_length_der(*der_len,der,&len_len); + } *der_len+=len_len; - free(temp); + _asn1_afree(temp); + + if(max_len<(*der_len)) return ASN1_MEM_ERROR; + + return ASN1_SUCCESS; } @@ -313,10 +338,13 @@ _asn1_bit_der(const unsigned char *str,int bit_len,unsigned char *der,int *der_l /* der: string with the DER coding of the whole tree*/ /* counter: number of meanful bytes of DER */ /* (der[0]..der[*counter-1]). */ +/* max_len: size of der vector */ /* Return: */ +/* ASN1_MEM_ERROR if der vector isn't big enough, */ +/* otherwise ASN1_SUCCESS. */ /******************************************************/ -void -_asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter) +asn1_retCode +_asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter,int *max_len) { node_asn *p; int is_tag_implicit,len2,len3; @@ -339,8 +367,11 @@ _asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter) len2=strtol(p->name,NULL,10); _asn1_set_name(p,NULL); _asn1_length_der(*counter-len2,temp,&len3); - memmove(der+len2+len3,der+len2,*counter-len2); - memcpy(der+len2,temp,len3); + if(len3<=(*max_len)){ + memmove(der+len2+len3,der+len2,*counter-len2); + memcpy(der+len2,temp,len3); + } + *max_len -= len3; *counter+=len3; is_tag_implicit=0; } @@ -353,6 +384,10 @@ _asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter) p=p->left; } } + + if(*max_len<0) return ASN1_MEM_ERROR; + + return ASN1_SUCCESS; } @@ -365,17 +400,20 @@ _asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter) /* der: string returned */ /* counter: number of meanful bytes of DER */ /* (counter[0]..der[*counter-1]). */ +/* max_len: size of der vector */ /* Return: */ /* ASN1_GENERIC_ERROR if the type is unknown, */ +/* ASN1_MEM_ERROR if der vector isn't big enough, */ /* otherwise ASN1_SUCCESS. */ /******************************************************/ -int -_asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter) +asn1_retCode +_asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter,int *max_len) { node_asn *p; int tag_len,is_tag_implicit; unsigned char class,class_implicit=0,temp[SIZEOF_UNSIGNED_INT*3+1]; unsigned long tag_implicit=0; + char tag_der[MAX_TAG_LEN]; is_tag_implicit=0; @@ -390,10 +428,15 @@ _asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter) if(p->type&CONST_EXPLICIT){ if(is_tag_implicit) - _asn1_tag_der(class_implicit,tag_implicit,der+*counter,&tag_len); + _asn1_tag_der(class_implicit,tag_implicit,tag_der,&tag_len); else - _asn1_tag_der(class|STRUCTURED,strtoul(p->value,NULL,10),der+*counter,&tag_len); + _asn1_tag_der(class|STRUCTURED,strtoul(p->value,NULL,10),tag_der,&tag_len); + + *max_len -= tag_len; + if(*max_len>=0) + memcpy(der+*counter,tag_der,tag_len); *counter+=tag_len; + _asn1_ltostr(*counter,temp); _asn1_set_name(p,temp); @@ -416,45 +459,45 @@ _asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter) } if(is_tag_implicit){ - _asn1_tag_der(class_implicit,tag_implicit,der+*counter,&tag_len); + _asn1_tag_der(class_implicit,tag_implicit,tag_der,&tag_len); } else{ switch(type_field(node->type)){ case TYPE_NULL: - _asn1_tag_der(UNIVERSAL,TAG_NULL,der+*counter,&tag_len); + _asn1_tag_der(UNIVERSAL,TAG_NULL,tag_der,&tag_len); break; case TYPE_BOOLEAN: - _asn1_tag_der(UNIVERSAL,TAG_BOOLEAN,der+*counter,&tag_len); + _asn1_tag_der(UNIVERSAL,TAG_BOOLEAN,tag_der,&tag_len); break; case TYPE_INTEGER: - _asn1_tag_der(UNIVERSAL,TAG_INTEGER,der+*counter,&tag_len); + _asn1_tag_der(UNIVERSAL,TAG_INTEGER,tag_der,&tag_len); break; case TYPE_ENUMERATED: - _asn1_tag_der(UNIVERSAL,TAG_ENUMERATED,der+*counter,&tag_len); + _asn1_tag_der(UNIVERSAL,TAG_ENUMERATED,tag_der,&tag_len); break; case TYPE_OBJECT_ID: - _asn1_tag_der(UNIVERSAL,TAG_OBJECT_ID,der+*counter,&tag_len); + _asn1_tag_der(UNIVERSAL,TAG_OBJECT_ID,tag_der,&tag_len); break; case TYPE_TIME: if(node->type&CONST_UTC){ - _asn1_tag_der(UNIVERSAL,TAG_UTCTime,der+*counter,&tag_len); + _asn1_tag_der(UNIVERSAL,TAG_UTCTime,tag_der,&tag_len); } - else _asn1_tag_der(UNIVERSAL,TAG_GENERALIZEDTime,der+*counter,&tag_len); + else _asn1_tag_der(UNIVERSAL,TAG_GENERALIZEDTime,tag_der,&tag_len); break; case TYPE_OCTET_STRING: - _asn1_tag_der(UNIVERSAL,TAG_OCTET_STRING,der+*counter,&tag_len); + _asn1_tag_der(UNIVERSAL,TAG_OCTET_STRING,tag_der,&tag_len); break; case TYPE_GENERALSTRING: - _asn1_tag_der(UNIVERSAL,TAG_GENERALSTRING,der+*counter,&tag_len); + _asn1_tag_der(UNIVERSAL,TAG_GENERALSTRING,tag_der,&tag_len); break; case TYPE_BIT_STRING: - _asn1_tag_der(UNIVERSAL,TAG_BIT_STRING,der+*counter,&tag_len); + _asn1_tag_der(UNIVERSAL,TAG_BIT_STRING,tag_der,&tag_len); break; case TYPE_SEQUENCE: case TYPE_SEQUENCE_OF: - _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SEQUENCE,der+*counter,&tag_len); + _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SEQUENCE,tag_der,&tag_len); break; case TYPE_SET: case TYPE_SET_OF: - _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SET,der+*counter,&tag_len); + _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SET,tag_der,&tag_len); break; case TYPE_TAG: tag_len=0; @@ -469,9 +512,14 @@ _asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter) return ASN1_GENERIC_ERROR; } } - + + *max_len -= tag_len; + if(*max_len>=0) + memcpy(der+*counter,tag_der,tag_len); *counter+=tag_len; + if(*max_len<0) return ASN1_MEM_ERROR; + return ASN1_SUCCESS; } @@ -670,7 +718,7 @@ _asn1_ordering_set_of(unsigned char *der,node_asn *node) * @element: pointer to an ASN1 element * @name: the name of the structure you want to encode (it must be inside *POINTER). * @der: vector that will contain the DER encoding. DER must be a pointer to memory cells already allocated. - * @len: number of bytes of *der: der[0]..der[len-1] + * @len: number of bytes of *der: der[0]..der[len-1], Initialy holds the sizeof of der vector. * @errorDescription : return the error description or an empty string if success. * Description: * @@ -683,6 +731,10 @@ _asn1_ordering_set_of(unsigned char *der,node_asn *node) * ASN1_ELEMENT_NOT_FOUND\: NAME is not a valid element. * * ASN1_VALUE_NOT_FOUND\: there is an element without a value. + * + * ASN1_MEM_ERROR\: der vector isn't big enough. Also in this case LEN + * will contain the length needed. + * **/ asn1_retCode asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len, @@ -690,72 +742,132 @@ asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len, { node_asn *node,*p; char temp[SIZEOF_UNSIGNED_LONG_INT*3+1]; - int counter,counter_old,len2,len3,move,ris; + int counter,counter_old,len2,len3,move,max_len,max_len_old; + asn1_retCode ris; node=_asn1_find_node(element,name); if(node==NULL) return ASN1_ELEMENT_NOT_FOUND; + max_len=*len; + counter=0; move=DOWN; p=node; while(1){ counter_old=counter; - if(move!=UP) ris=_asn1_insert_tag_der(p,der,&counter); - + max_len_old=max_len; + if(move!=UP){ + ris=_asn1_insert_tag_der(p,der,&counter,&max_len); + } switch(type_field(p->type)){ case TYPE_NULL: - der[counter]=0; - counter++; + max_len--; + if(max_len>=0) + der[counter++]=0; move=RIGHT; break; case TYPE_BOOLEAN: - if((p->type&CONST_DEFAULT) && (p->value==NULL)) counter=counter_old; + if((p->type&CONST_DEFAULT) && (p->value==NULL)){ + counter=counter_old; + max_len=max_len_old; + } else{ - der[counter++]=1; - if(p->value[0]=='F') der[counter++]=0; - else der[counter++]=0xFF; + if(p->value==NULL){ + _asn1_error_description_value_not_found(p,ErrorDescription); + return ASN1_VALUE_NOT_FOUND; + } + max_len -= 2; + if(max_len>=0){ + der[counter++]=1; + if(p->value[0]=='F') der[counter++]=0; + else der[counter++]=0xFF; + } + else + counter+=2; } move=RIGHT; break; case TYPE_INTEGER: case TYPE_ENUMERATED: - if((p->type&CONST_DEFAULT) && (p->value==NULL)) counter=counter_old; + if((p->type&CONST_DEFAULT) && (p->value==NULL)){ + counter=counter_old; + max_len=max_len_old; + } else{ if(p->value==NULL){ _asn1_error_description_value_not_found(p,ErrorDescription); return ASN1_VALUE_NOT_FOUND; } len2=_asn1_get_length_der(p->value,&len3); - memcpy(der+counter,p->value,len3+len2); + max_len -= len2+len3; + if(max_len>=0) + memcpy(der+counter,p->value,len3+len2); counter+=len3+len2; } move=RIGHT; break; case TYPE_OBJECT_ID: - _asn1_objectid_der(p->value,der+counter,&len2); - counter+=len2; + if((p->type&CONST_DEFAULT) && (p->value==NULL)){ + counter=counter_old; + max_len=max_len_old; + } + else{ + if(p->value==NULL){ + _asn1_error_description_value_not_found(p,ErrorDescription); + return ASN1_VALUE_NOT_FOUND; + } + len2=max_len; + ris=_asn1_objectid_der(p->value,der+counter,&len2); + if(ris==ASN1_MEM_ALLOC_ERROR) return ris; + max_len-=len2; + counter+=len2; + } move=RIGHT; break; case TYPE_TIME: - _asn1_time_der(p->value,der+counter,&len2); + if(p->value==NULL){ + _asn1_error_description_value_not_found(p,ErrorDescription); + return ASN1_VALUE_NOT_FOUND; + } + len2=max_len; + ris=_asn1_time_der(p->value,der+counter,&len2); + max_len-=len2; counter+=len2; move=RIGHT; break; case TYPE_OCTET_STRING: + if(p->value==NULL){ + _asn1_error_description_value_not_found(p,ErrorDescription); + return ASN1_VALUE_NOT_FOUND; + } len2=_asn1_get_length_der(p->value,&len3); - memcpy(der+counter,p->value,len3+len2); + max_len-=len2+len3; + if(max_len>=0) + memcpy(der+counter,p->value,len3+len2); counter+=len3+len2; move=RIGHT; break; case TYPE_GENERALSTRING: + if(p->value==NULL){ + _asn1_error_description_value_not_found(p,ErrorDescription); + return ASN1_VALUE_NOT_FOUND; + } len2=_asn1_get_length_der(p->value,&len3); - memcpy(der+counter,p->value,len3+len2); + max_len-=len2+len3; + if(max_len>=0) + memcpy(der+counter,p->value,len3+len2); counter+=len3+len2; move=RIGHT; break; case TYPE_BIT_STRING: + if(p->value==NULL){ + _asn1_error_description_value_not_found(p,ErrorDescription); + return ASN1_VALUE_NOT_FOUND; + } len2=_asn1_get_length_der(p->value,&len3); - memcpy(der+counter,p->value,len3+len2); + max_len-=len2+len3; + if(max_len>=0) + memcpy(der+counter,p->value,len3+len2); counter+=len3+len2; move=RIGHT; break; @@ -768,10 +880,14 @@ asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len, else{ /* move==UP */ len2=strtol(p->value,NULL,10); _asn1_set_value(p,NULL,0); - if(type_field(p->type)==TYPE_SET) _asn1_ordering_set(der+len2,p); + if((type_field(p->type)==TYPE_SET) && (max_len>=0)) + _asn1_ordering_set(der+len2,p); _asn1_length_der(counter-len2,temp,&len3); - memmove(der+len2+len3,der+len2,counter-len2); - memcpy(der+len2,temp,len3); + max_len-=len3; + if(max_len>=0){ + memmove(der+len2+len3,der+len2,counter-len2); + memcpy(der+len2,temp,len3); + } counter+=len3; move=RIGHT; } @@ -793,17 +909,27 @@ asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len, if(move==UP){ len2=strtol(p->value,NULL,10); _asn1_set_value(p,NULL,0); - if(type_field(p->type)==TYPE_SET_OF) _asn1_ordering_set_of(der+len2,p); + if((type_field(p->type)==TYPE_SET_OF) && (max_len>=0)) + _asn1_ordering_set_of(der+len2,p); _asn1_length_der(counter-len2,temp,&len3); - memmove(der+len2+len3,der+len2,counter-len2); - memcpy(der+len2,temp,len3); + max_len-=len3; + if(max_len>=0){ + memmove(der+len2+len3,der+len2,counter-len2); + memcpy(der+len2,temp,len3); + } counter+=len3; move=RIGHT; } break; case TYPE_ANY: + if(p->value==NULL){ + _asn1_error_description_value_not_found(p,ErrorDescription); + return ASN1_VALUE_NOT_FOUND; + } len2=_asn1_get_length_der(p->value,&len3); - memcpy(der+counter,p->value+len3,len2); + max_len-=len2; + if(max_len>=0) + memcpy(der+counter,p->value+len3,len2); counter+=len2; move=RIGHT; break; @@ -812,8 +938,9 @@ asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len, break; } - if((move!=DOWN) && (counter!=counter_old)) - _asn1_complete_explicit_tag(p,der,&counter); + if((move!=DOWN) && (counter!=counter_old)){ + ris=_asn1_complete_explicit_tag(p,der,&counter,&max_len); + } if(p==node && move!=DOWN) break; @@ -829,6 +956,9 @@ asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len, } *len=counter; + + if(max_len<0) return ASN1_MEM_ERROR; + return ASN1_SUCCESS; } diff --git a/asn1/lib/decoding.c b/asn1/lib/decoding.c index 811a4761..29dc9c9e 100644 --- a/asn1/lib/decoding.c +++ b/asn1/lib/decoding.c @@ -102,14 +102,15 @@ _asn1_get_octet_der(const unsigned char *der,int *der_len,unsigned char *str,int { int len_len; - if(str==NULL) return ASN1_SUCCESS; + /* if(str==NULL) return ASN1_SUCCESS; */ *str_len=_asn1_get_length_der(der,&len_len); + + *der_len=*str_len+len_len; if ( str_size >= *str_len) memcpy(str,der+len_len,*str_len); else { return ASN1_MEM_ERROR; } - *der_len=*str_len+len_len; return ASN1_SUCCESS; } @@ -171,14 +172,14 @@ _asn1_get_bit_der(const unsigned char *der,int *der_len,unsigned char *str, int if(str==NULL) return ASN1_SUCCESS; len_byte=_asn1_get_length_der(der,&len_len)-1; - + + *der_len=len_byte+len_len+1; if (str_size >= len_byte) memcpy(str,der+len_len+1,len_byte); else { return ASN1_MEM_ERROR; } *bit_len=len_byte*8-der[len_len]; - *der_len=len_byte+len_len+1; return ASN1_SUCCESS; } @@ -601,7 +602,7 @@ asn1_der_decoding(ASN1_TYPE *element,const unsigned char *der,int len, temp2=(unsigned char *)_asn1_alloca(len2+len3+len4); if (temp2==NULL){ asn1_delete_structure(element); - return ASN1_MEM_ERROR; + return ASN1_MEM_ALLOC_ERROR; } _asn1_octet_der(der+counter,len2+len3,temp2,&len4); @@ -668,6 +669,7 @@ asn1_der_decoding(ASN1_TYPE *element,const unsigned char *der,int len, * ASN1_ELEMENT_NOT_FOUND\: ELEMENT is ASN1_TYPE_EMPTY or elementName == NULL. * * ASN1_TAG_ERROR,ASN1_DER_ERROR\: the der encoding doesn't match the structure STRUCTURE. *ELEMENT deleted. + * **/ asn1_retCode asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, @@ -699,7 +701,7 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, if(nameLen>0) strcpy(currentName,(*structure)->name); else{ asn1_delete_structure(structure); - return ASN1_MEM_ERROR; + return ASN1_MEM_ERROR; } if(!(strcmp(currentName,elementName))){ state=FOUND; @@ -999,7 +1001,7 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, temp2=(unsigned char *)_asn1_alloca(len2+len3+len4); if (temp2==NULL){ asn1_delete_structure(structure); - return ASN1_MEM_ERROR; + return ASN1_MEM_ALLOC_ERROR; } _asn1_octet_der(der+counter,len2+len3,temp2,&len4); diff --git a/asn1/lib/element.c b/asn1/lib/element.c index c38c8b97..207ff67b 100644 --- a/asn1/lib/element.c +++ b/asn1/lib/element.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000,2001 Fabio Fiorina + * Copyright (C) 2000,2001,2002,2003 Fabio Fiorina * * This file is part of LIBASN1. * @@ -69,7 +69,7 @@ _asn1_hierarchical_name(node_asn *node,char *name,int name_size) /* allocated). */ /* value_out_size: number of bytes of value_out. */ /* len: number of significant byte of value_out. */ -/* Return: ASN1_MEM_ERROR or ASN1_SUCCESS */ +/* Return: ASN1_MEM_ERROR or ASN1_SUCCESS */ /******************************************************************/ asn1_retCode _asn1_convert_integer(const char *value,unsigned char *value_out,int value_out_size, int *len) @@ -87,7 +87,7 @@ _asn1_convert_integer(const char *value,unsigned char *value_out,int value_out_s if(val[0]&0x80) negative=1; else negative=0; - + for(k=0;k value_out_size) /* VALUE_OUT is too short to contain the value convertion */ return ASN1_MEM_ERROR; @@ -103,8 +105,6 @@ _asn1_convert_integer(const char *value,unsigned char *value_out,int value_out_s for(k2=k;k2type)==TYPE_CONSTANT){ if((p->name) && (!strcmp(p->name,value))){ value_temp=(unsigned char *)_asn1_alloca(SIZEOF_UNSIGNED_LONG_INT); - if (value_temp==NULL) return ASN1_MEM_ERROR; + if (value_temp==NULL) return ASN1_MEM_ALLOC_ERROR; _asn1_convert_integer(p->value,value_temp,SIZEOF_UNSIGNED_LONG_INT, &len); break; @@ -318,7 +318,7 @@ asn1_write_value(node_asn *node_root,const char *name, } else{ /* len != 0 */ value_temp=(unsigned char *)_asn1_alloca(len); - if (value_temp==NULL) return ASN1_MEM_ERROR; + if (value_temp==NULL) return ASN1_MEM_ALLOC_ERROR; memcpy(value_temp,value,len); } @@ -338,7 +338,7 @@ asn1_write_value(node_asn *node_root,const char *name, _asn1_length_der(len-k,NULL,&len2); temp=(unsigned char *)_asn1_alloca(len-k+len2); - if (temp==NULL) return ASN1_MEM_ERROR; + if (temp==NULL) return ASN1_MEM_ALLOC_ERROR; _asn1_octet_der(value_temp+k,len-k,temp,&len2); _asn1_set_value(node,temp,len2); @@ -351,7 +351,7 @@ asn1_write_value(node_asn *node_root,const char *name, while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; if((isdigit(p->value[0])) || (p->value[0]=='-')){ default_temp=(unsigned char *)_asn1_alloca(SIZEOF_UNSIGNED_LONG_INT); - if (default_temp==NULL) return ASN1_MEM_ERROR; + if (default_temp==NULL) return ASN1_MEM_ALLOC_ERROR; _asn1_convert_integer(p->value,default_temp,SIZEOF_UNSIGNED_LONG_INT,&len2); } @@ -362,7 +362,7 @@ asn1_write_value(node_asn *node_root,const char *name, if(type_field(p2->type)==TYPE_CONSTANT){ if((p2->name) && (!strcmp(p2->name,p->value))){ default_temp=(unsigned char *)_asn1_alloca(SIZEOF_UNSIGNED_LONG_INT); - if (default_temp==NULL) return ASN1_MEM_ERROR; + if (default_temp==NULL) return ASN1_MEM_ALLOC_ERROR; _asn1_convert_integer(p2->value,default_temp,SIZEOF_UNSIGNED_LONG_INT,&len2); break; @@ -389,6 +389,14 @@ asn1_write_value(node_asn *node_root,const char *name, for(k=0;ktype&CONST_DEFAULT){ + p=node->down; + while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; + if(!strcmp(value,p->value)){ + _asn1_set_value(node,NULL,0); + break; + } + } _asn1_set_value(node,value,strlen(value)+1); break; case TYPE_TIME: @@ -430,7 +438,7 @@ asn1_write_value(node_asn *node_root,const char *name, len=strlen(value); _asn1_length_der(len,NULL,&len2); temp=(unsigned char *)_asn1_alloca(len+len2); - if (temp==NULL) return ASN1_MEM_ERROR; + if (temp==NULL) return ASN1_MEM_ALLOC_ERROR; _asn1_octet_der(value,len,temp,&len2); _asn1_set_value(node,temp,len2); @@ -441,7 +449,7 @@ asn1_write_value(node_asn *node_root,const char *name, len=strlen(value); _asn1_length_der(len,NULL,&len2); temp=(unsigned char *)_asn1_alloca(len+len2); - if (temp==NULL) return ASN1_MEM_ERROR; + if (temp==NULL) return ASN1_MEM_ALLOC_ERROR; _asn1_octet_der(value,len,temp,&len2); _asn1_set_value(node,temp,len2); @@ -452,7 +460,7 @@ asn1_write_value(node_asn *node_root,const char *name, len=strlen(value); _asn1_length_der((len>>3)+2,NULL,&len2); temp=(unsigned char *)_asn1_alloca((len>>3)+2+len2); - if (temp==NULL) return ASN1_MEM_ERROR; + if (temp==NULL) return ASN1_MEM_ALLOC_ERROR; _asn1_bit_der(value,len,temp,&len2); _asn1_set_value(node,temp,len2); @@ -476,7 +484,7 @@ asn1_write_value(node_asn *node_root,const char *name, case TYPE_ANY: _asn1_length_der(len,NULL,&len2); temp=(unsigned char *)_asn1_alloca(len+len2); - if (temp==NULL) return ASN1_MEM_ERROR; + if (temp==NULL) return ASN1_MEM_ALLOC_ERROR; _asn1_octet_der(value,len,temp,&len2); _asn1_set_value(node,temp,len2); @@ -540,6 +548,9 @@ asn1_write_value(node_asn *node_root,const char *name, * ASN1_ELEMENT_NOT_FOUND\: NAME is not a valid element. * * ASN1_VALUE_NOT_FOUND\: there isn't any value for the element selected. + * + * ASN1_MEM_ERROR\: the value vector isn't big enough to store the result. + * In this case LEN will contain the number of bytes needed. * * Examples: * a description for each type @@ -585,7 +596,7 @@ asn1_write_value(node_asn *node_root,const char *name, asn1_retCode asn1_read_value(node_asn *root,const char *name,unsigned char *value, int *len) { - node_asn *node,*p; + node_asn *node,*p,*p2; int len2,len3; int value_size = *len; @@ -623,7 +634,25 @@ asn1_read_value(node_asn *root,const char *name,unsigned char *value, int *len) if((node->type&CONST_DEFAULT) && (node->value==NULL)){ p=node->down; while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; - if (_asn1_convert_integer(p->value,value,value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR; + if((isdigit(p->value[0])) || (p->value[0]=='-') || (p->value[0]=='+')){ + if (_asn1_convert_integer(p->value,value,value_size, len) != + ASN1_SUCCESS) + return ASN1_MEM_ERROR; + } + else{ /* is an identifier like v1 */ + p2=node->down; + while(p2){ + if(type_field(p2->type)==TYPE_CONSTANT){ + if((p2->name) && (!strcmp(p2->name,p->value))){ + if (_asn1_convert_integer(p2->value,value,value_size, len) != + ASN1_SUCCESS) + return ASN1_MEM_ERROR; + break; + } + } + p2=p2->right; + } + } } else{ len2=-1; @@ -636,17 +665,21 @@ asn1_read_value(node_asn *root,const char *name,unsigned char *value, int *len) p=node->down; while(p){ if(type_field(p->type)==TYPE_CONSTANT){ - value_size-=strlen(p->value)+1; - if(value_size<1) return ASN1_MEM_ERROR; - strcat(value,p->value); + ADD_STR_VALUE(value,value_size,p->value); if(p->right) { - strcat(value,"."); + ADD_STR_VALUE(value,value_size,"."); } } p=p->right; } *len = strlen(value) + 1; - } else { + } + else if((node->type&CONST_DEFAULT) && (node->value==NULL)){ + p=node->down; + while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; + PUT_STR_VALUE(value, value_size, p->value); + } + else { PUT_STR_VALUE(value, value_size, node->value); } break; @@ -685,8 +718,8 @@ asn1_read_value(node_asn *root,const char *name,unsigned char *value, int *len) * asn1_read_tag - Returns the TAG of one element inside a structure * @root: pointer to a structure * @name: the name of the element inside a structure. - * @tag: variable that will contain the TAG value. - * @class: variable that will specify the TAG type. + * @tagValue: variable that will contain the TAG value. + * @classValue: variable that will specify the TAG type. * * Description: * @@ -702,7 +735,7 @@ asn1_read_value(node_asn *root,const char *name,unsigned char *value, int *len) * **/ asn1_retCode -asn1_read_tag(node_asn *root,const char *name,int *tag, int *class) +asn1_read_tag(node_asn *root,const char *name,int *tagValue, int *classValue) { node_asn *node,*p,*pTag; @@ -726,43 +759,43 @@ asn1_read_tag(node_asn *root,const char *name,int *tag, int *class) } if(pTag){ - *tag=strtoul(pTag->value,NULL,10); + *tagValue=strtoul(pTag->value,NULL,10); - if(pTag->type&CONST_APPLICATION) *class=ASN1_CLASS_APPLICATION; - else if(pTag->type&CONST_UNIVERSAL) *class=ASN1_CLASS_UNIVERSAL; - else if(pTag->type&CONST_PRIVATE) *class=ASN1_CLASS_PRIVATE; - else *class=ASN1_CLASS_CONTEXT_SPECIFIC; + if(pTag->type&CONST_APPLICATION) *classValue=ASN1_CLASS_APPLICATION; + else if(pTag->type&CONST_UNIVERSAL) *classValue=ASN1_CLASS_UNIVERSAL; + else if(pTag->type&CONST_PRIVATE) *classValue=ASN1_CLASS_PRIVATE; + else *classValue=ASN1_CLASS_CONTEXT_SPECIFIC; } else{ - *class=ASN1_CLASS_UNIVERSAL; + *classValue=ASN1_CLASS_UNIVERSAL; switch(type_field(node->type)){ case TYPE_NULL: - *tag=ASN1_TAG_NULL;break; + *tagValue=ASN1_TAG_NULL;break; case TYPE_BOOLEAN: - *tag=ASN1_TAG_BOOLEAN;break; + *tagValue=ASN1_TAG_BOOLEAN;break; case TYPE_INTEGER: - *tag=ASN1_TAG_INTEGER;break; + *tagValue=ASN1_TAG_INTEGER;break; case TYPE_ENUMERATED: - *tag=ASN1_TAG_ENUMERATED;break; + *tagValue=ASN1_TAG_ENUMERATED;break; case TYPE_OBJECT_ID: - *tag=ASN1_TAG_OBJECT_ID;break; + *tagValue=ASN1_TAG_OBJECT_ID;break; case TYPE_TIME: if(node->type&CONST_UTC){ - *tag=ASN1_TAG_UTCTime; + *tagValue=ASN1_TAG_UTCTime; } - else *tag=ASN1_TAG_GENERALIZEDTime; + else *tagValue=ASN1_TAG_GENERALIZEDTime; break; case TYPE_OCTET_STRING: - *tag=ASN1_TAG_OCTET_STRING;break; + *tagValue=ASN1_TAG_OCTET_STRING;break; case TYPE_GENERALSTRING: - *tag=ASN1_TAG_GENERALSTRING;break; + *tagValue=ASN1_TAG_GENERALSTRING;break; case TYPE_BIT_STRING: - *tag=ASN1_TAG_BIT_STRING;break; + *tagValue=ASN1_TAG_BIT_STRING;break; case TYPE_SEQUENCE: case TYPE_SEQUENCE_OF: - *tag=ASN1_TAG_SEQUENCE;break; + *tagValue=ASN1_TAG_SEQUENCE;break; case TYPE_SET: case TYPE_SET_OF: - *tag=ASN1_TAG_SET;break; + *tagValue=ASN1_TAG_SET;break; case TYPE_TAG: case TYPE_CHOICE: case TYPE_ANY: diff --git a/asn1/lib/errors.c b/asn1/lib/errors.c index bc51e9fe..70f38cb3 100644 --- a/asn1/lib/errors.c +++ b/asn1/lib/errors.c @@ -47,6 +47,7 @@ static libtasn1_error_entry error_algorithms[] = { LIBTASN1_ERROR_ENTRY( ASN1_ERROR_TYPE_ANY ), LIBTASN1_ERROR_ENTRY( ASN1_SYNTAX_ERROR ), LIBTASN1_ERROR_ENTRY( ASN1_MEM_ERROR ), + LIBTASN1_ERROR_ENTRY( ASN1_MEM_ALLOC_ERROR ), LIBTASN1_ERROR_ENTRY( ASN1_DER_OVERFLOW ), LIBTASN1_ERROR_ENTRY( ASN1_NAME_TOO_LONG ), LIBTASN1_ERROR_ENTRY( ASN1_ARRAY_ERROR ), diff --git a/asn1/lib/errors_int.h b/asn1/lib/errors_int.h index 351dd26d..6d2706f0 100644 --- a/asn1/lib/errors_int.h +++ b/asn1/lib/errors_int.h @@ -15,9 +15,10 @@ #define ASN1_ERROR_TYPE_ANY 10 #define ASN1_SYNTAX_ERROR 11 #define ASN1_MEM_ERROR 12 -#define ASN1_DER_OVERFLOW 13 -#define ASN1_NAME_TOO_LONG 14 -#define ASN1_ARRAY_ERROR 15 -#define ASN1_ELEMENT_NOT_EMPTY 16 +#define ASN1_MEM_ALLOC_ERROR 13 +#define ASN1_DER_OVERFLOW 14 +#define ASN1_NAME_TOO_LONG 15 +#define ASN1_ARRAY_ERROR 16 +#define ASN1_ELEMENT_NOT_EMPTY 17 diff --git a/asn1/lib/int.h b/asn1/lib/int.h index f9c62b3c..0daed1d3 100644 --- a/asn1/lib/int.h +++ b/asn1/lib/int.h @@ -32,6 +32,8 @@ #include +#define LIBTASN1_VERSION "0.2.4" + #define MAX32 4294967295 #define MAX24 16777215 #define MAX16 65535 diff --git a/asn1/lib/libtasn1.h b/asn1/lib/libtasn1.h index 31ceee31..89f73e14 100644 --- a/asn1/lib/libtasn1.h +++ b/asn1/lib/libtasn1.h @@ -28,7 +28,7 @@ extern "C" { #endif -#define LIBASN1_VERSION "0.2.1" +#define LIBTASN1_VERSION "0.2.4" #include #include @@ -58,10 +58,11 @@ typedef int asn1_retCode; /* type returned by libasn1 functions */ #define ASN1_ERROR_TYPE_ANY 10 #define ASN1_SYNTAX_ERROR 11 #define ASN1_MEM_ERROR 12 -#define ASN1_DER_OVERFLOW 13 -#define ASN1_NAME_TOO_LONG 14 -#define ASN1_ARRAY_ERROR 15 -#define ASN1_ELEMENT_NOT_EMPTY 16 +#define ASN1_MEM_ALLOC_ERROR 13 +#define ASN1_DER_OVERFLOW 14 +#define ASN1_NAME_TOO_LONG 15 +#define ASN1_ARRAY_ERROR 16 +#define ASN1_ELEMENT_NOT_EMPTY 17 /*************************************/ /* Constants used in asn1_visit_tree */ @@ -170,11 +171,13 @@ asn1_retCode asn1_expand_any_defined_by(ASN1_TYPE definitions, asn1_retCode asn1_expand_octet_string(ASN1_TYPE definitions,ASN1_TYPE *element, const char *octetName,const char *objectName); -asn1_retCode asn1_read_tag(node_asn *root,const char *name,int *tag, - int *class); +asn1_retCode asn1_read_tag(node_asn *root,const char *name,int *tagValue, + int *classValue); -asn1_retCode asn1_find_structure_from_oid(ASN1_TYPE definitions, - const char *oidValue,char *structureName); +const char* asn1_find_structure_from_oid(ASN1_TYPE definitions, + const char *oidValue); + +const char *asn1_check_version( const char *req_version ); const char* libtasn1_strerror(asn1_retCode error); diff --git a/asn1/lib/parser_aux.c b/asn1/lib/parser_aux.c index a0f7775a..6f33563f 100644 --- a/asn1/lib/parser_aux.c +++ b/asn1/lib/parser_aux.c @@ -518,7 +518,7 @@ asn1_retCode _asn1_expand_object_id(ASN1_TYPE node) { node_asn *p,*p2,*p3,*p4,*p5; - char name_root[129],name2[129]; + char name_root[MAX_NAME_SIZE],name2[2*MAX_NAME_SIZE+1]; int move; if(node==NULL) return ASN1_ELEMENT_NOT_FOUND; @@ -584,6 +584,55 @@ _asn1_expand_object_id(ASN1_TYPE node) if(move==UP) p=_asn1_find_up(p); } + + /*******************************/ + /* expand DEFAULT */ + /*******************************/ + p=node; + move=DOWN; + + while(!((p==node) && (move==UP))){ + if(move!=UP){ + if((type_field(p->type)==TYPE_OBJECT_ID) && + (p->type&CONST_DEFAULT)){ + p2=p->down; + if(p2 && (type_field(p2->type)==TYPE_DEFAULT)){ + _asn1_str_cpy(name2, sizeof(name2), name_root); + _asn1_str_cat(name2, sizeof(name2), "."); + _asn1_str_cat(name2, sizeof(name2), p2->value); + p3=_asn1_find_node(node,name2); + if(!p3 || (type_field(p3->type)!=TYPE_OBJECT_ID) || + !(p3->type&CONST_ASSIGN)) return ASN1_ELEMENT_NOT_FOUND; + p4=p3->down; + name2[0]=0; + while(p4){ + if(type_field(p4->type)==TYPE_CONSTANT){ + if(name2[0]) _asn1_str_cat(name2,sizeof(name2),"."); + _asn1_str_cat(name2,sizeof(name2),p4->value); + } + p4=p4->right; + } + _asn1_set_value(p2,name2,strlen(name2)+1); + } + } + move=DOWN; + } + else move=RIGHT; + + if(move==DOWN){ + if(p->down) p=p->down; + else move=RIGHT; + } + + if(p==node) {move=UP; continue;} + + if(move==RIGHT){ + if(p->right) p=p->right; + else move=UP; + } + if(move==UP) p=_asn1_find_up(p); + } + return ASN1_SUCCESS; } @@ -675,6 +724,22 @@ _asn1_check_identifier(ASN1_TYPE node) } } else if((type_field(p->type)==TYPE_OBJECT_ID) && + (p->type&CONST_DEFAULT)){ + p2=p->down; + if(p2 && (type_field(p2->type)==TYPE_DEFAULT)){ + _asn1_str_cpy(name2, sizeof(name2), node->name); + _asn1_str_cat(name2, sizeof(name2), "."); + _asn1_str_cat(name2, sizeof(name2), p2->value); + strcpy(_asn1_identifierMissing,p2->value); + p2=_asn1_find_node(node,name2); + if(!p2 || (type_field(p2->type)!=TYPE_OBJECT_ID) || + !(p2->type&CONST_ASSIGN)) + return ASN1_IDENTIFIER_NOT_FOUND; + else + _asn1_identifierMissing[0]=0; + } + } + else if((type_field(p->type)==TYPE_OBJECT_ID) && (p->type&CONST_ASSIGN)){ p2=p->down; if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){ @@ -768,4 +833,79 @@ _asn1_set_default_tag(ASN1_TYPE node) +static const char* +parse_version_number( const char *s, int *number ) +{ + int val = 0; + + if( *s == '0' && isdigit(s[1]) ) + return NULL; /* leading zeros are not allowed */ + for ( ; isdigit(*s); s++ ) { + val *= 10; + val += *s - '0'; + } + *number = val; + return val < 0? NULL : s; +} + +/* The parse version functions were copied from libgcrypt. + */ +static const char * +parse_version_string( const char *s, int *major, int *minor, int *micro ) +{ + s = parse_version_number( s, major ); + if( !s || *s != '.' ) + return NULL; + s++; + s = parse_version_number( s, minor ); + if( !s || *s != '.' ) + return NULL; + s++; + s = parse_version_number( s, micro ); + if( !s ) + return NULL; + return s; /* patchlevel */ +} + +/** + * asn1_check_version - This function checks the library's version + * @req_version: the version to check + * + * Check that the the version of the library is at minimum the requested one + * and return the version string; return NULL if the condition is not + * satisfied. If a NULL is passed to this function, no check is done, + * but the version string is simply returned. + * + **/ +const char * +asn1_check_version( const char *req_version ) +{ + const char *ver = LIBTASN1_VERSION; + int my_major, my_minor, my_micro; + int rq_major, rq_minor, rq_micro; + const char *my_plvl, *rq_plvl; + + if ( !req_version ) + return ver; + + my_plvl = parse_version_string( ver, &my_major, &my_minor, &my_micro ); + if ( !my_plvl ) + return NULL; /* very strange our own version is bogus */ + rq_plvl = parse_version_string( req_version, &rq_major, &rq_minor, + &rq_micro ); + if ( !rq_plvl ) + return NULL; /* req version string is invalid */ + + if ( my_major > rq_major + || (my_major == rq_major && my_minor > rq_minor) + || (my_major == rq_major && my_minor == rq_minor + && my_micro > rq_micro) + || (my_major == rq_major && my_minor == rq_minor + && my_micro == rq_micro + && strcmp( my_plvl, rq_plvl ) >= 0) ) { + return ver; + } + return NULL; +} + diff --git a/asn1/lib/structure.c b/asn1/lib/structure.c index 7eb6fdec..1291a009 100644 --- a/asn1/lib/structure.c +++ b/asn1/lib/structure.c @@ -860,24 +860,21 @@ asn1_number_of_elements(ASN1_TYPE element,const char *name,int *num) * after an OID definition. * @definitions: ASN1 definitions * @oidValue: value of the OID to search (e.g. "1.2.3.4"). - * @structureName: name returned by the function, that is the structure - * defined just after the OID of value equal to OIDVALUE. - * It must be an array of MAX_NAME_SIZE char elements. - * * Description: * * Search the structure that is defined just after an OID definition. * * Returns: * - * ASN1_SUCCESS\: structure found. + * NULL when OIDVALUE not found, * - * ASN1_ELEMENT_NOT_FOUND\: OID equal to OIDVALUE not found. + * otherwise the pointer to a constant string that contains the element + * name defined just after the OID. * **/ -asn1_retCode +const char* asn1_find_structure_from_oid(ASN1_TYPE definitions, - const char *oidValue,char *structureName) + const char *oidValue) { char definitionsName[MAX_NAME_SIZE],name[2*MAX_NAME_SIZE+1]; char value[MAX_NAME_SIZE]; @@ -886,7 +883,7 @@ asn1_find_structure_from_oid(ASN1_TYPE definitions, asn1_retCode result; if((definitions==ASN1_TYPE_EMPTY) || (oidValue==NULL)) - return ASN1_ELEMENT_NOT_FOUND; + return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ strcpy(definitionsName,definitions->name); @@ -906,16 +903,15 @@ asn1_find_structure_from_oid(ASN1_TYPE definitions, if((result == ASN1_SUCCESS) && (!strcmp(oidValue,value))){ p=p->right; if(p==NULL) /* reach the end of ASN1 definitions */ - return ASN1_ELEMENT_NOT_FOUND; + return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ - strcpy(structureName,p->name); - return ASN1_SUCCESS; + return p->name; } } p=p->right; } - return ASN1_ELEMENT_NOT_FOUND; + return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ } diff --git a/asn1/src/CertificateExample.c b/asn1/src/CertificateExample.c index 2f3bf96d..fc60cf9e 100644 --- a/asn1/src/CertificateExample.c +++ b/asn1/src/CertificateExample.c @@ -186,6 +186,9 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len) ASN1_TYPE param=ASN1_TYPE_EMPTY; ASN1_TYPE constr=ASN1_TYPE_EMPTY; char errorDescription[MAX_ERROR_DESCRIPTION_SIZE]; + int max_len; + + max_len=*der_len; result=asn1_create_element(cert_def,"PKIX1Implicit88.Certificate",&cert1); @@ -222,6 +225,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len) result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName", &value); result=asn1_write_value(value,"","US",2); + *der_len = max_len; result=asn1_der_coding(value,"",der,der_len,errorDescription); asn1_delete_structure(&value); result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len); @@ -237,6 +241,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len) &value); result=asn1_write_value(value,"","printableString",1); result=asn1_write_value(value,"printableString","gov",3); + *der_len = max_len; result=asn1_der_coding(value,"",der,der_len,errorDescription); asn1_delete_structure(&value); result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len); @@ -253,6 +258,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len) result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value); result=asn1_write_value(value,"","printableString",1); result=asn1_write_value(value,"printableString","nist",4); + *der_len = max_len; result=asn1_der_coding(value,"",der,der_len,errorDescription); asn1_delete_structure(&value); result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len); @@ -279,6 +285,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len) result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName", &value); result=asn1_write_value(value,"","US",2); + *der_len = max_len; result=asn1_der_coding(value,"",der,der_len,errorDescription); asn1_delete_structure(&value); result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len); @@ -294,6 +301,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len) &value); result=asn1_write_value(value,"","printableString",1); result=asn1_write_value(value,"printableString","gov",3); + *der_len = max_len; result=asn1_der_coding(value,"",der,der_len,errorDescription); asn1_delete_structure(&value); result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len); @@ -309,6 +317,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len) result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value); result=asn1_write_value(value,"","printableString",1); result=asn1_write_value(value,"printableString","nist",4); + *der_len = max_len; result=asn1_der_coding(value,"",der,der_len,errorDescription); asn1_delete_structure(&value); result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len); @@ -325,6 +334,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len) result=asn1_write_value(param,"q",str2,20); str2="\xd4\x38"; /* only an example */ result=asn1_write_value(param,"g",str2,128); + *der_len = max_len; result=asn1_der_coding(param,"",der,der_len,errorDescription); asn1_delete_structure(¶m); result=asn1_write_value(cert1,"tbsCertificate.subjectPublicKeyInfo.algorithm.parameters",der,*der_len); @@ -347,6 +357,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len) result=asn1_create_element(cert_def,"PKIX1Implicit88.BasicConstraints",&constr); result=asn1_write_value(constr,"cA","TRUE",1); result=asn1_write_value(constr,"pathLenConstraint",NULL,0); + *der_len = max_len; result=asn1_der_coding(constr,"",der,der_len,errorDescription); result=asn1_delete_structure(&constr); result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnValue",der,*der_len); @@ -370,6 +381,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len) /* signature */ + *der_len = max_len; result=asn1_der_coding(cert1,"tbsCertificate",der,der_len ,errorDescription); if(result!=ASN1_SUCCESS){ @@ -384,7 +396,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len) asn1_visit_tree(cert1,""); printf("-----------------\n"); */ - + *der_len = max_len; result=asn1_der_coding(cert1,"",der,der_len,errorDescription); if(result!=ASN1_SUCCESS){ printf("\n'certificate' encoding creation: ERROR\n"); @@ -501,7 +513,7 @@ main(int argc,char *argv[]) asn1_visit_tree(PKIX1Implicit88,"PKIX1Implicit88"); printf("-----------------\n"); */ - + der_len=1024; create_certificate(PKIX1Implicit88,der,&der_len); get_certificate(PKIX1Implicit88,der,der_len); diff --git a/asn1/src/CrlExample.c b/asn1/src/CrlExample.c index 1aafbd7f..2eba8c9c 100644 --- a/asn1/src/CrlExample.c +++ b/asn1/src/CrlExample.c @@ -194,6 +194,9 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len) ASN1_TYPE crl=ASN1_TYPE_EMPTY; ASN1_TYPE value=ASN1_TYPE_EMPTY; char errorDescription[MAX_ERROR_DESCRIPTION_SIZE]; + int max_len; + + max_len=*der_len; result=asn1_create_element(cert_def,"PKIX1Implicit88.CertificateList",&crl); @@ -226,6 +229,7 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len) result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName", &value); result=asn1_write_value(value,"","US",2); + *der_len=max_len; result=asn1_der_coding(value,"",der,der_len,errorDescription); asn1_delete_structure(&value); @@ -242,6 +246,7 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len) &value); result=asn1_write_value(value,"","printableString",1); result=asn1_write_value(value,"printableString","gov",3); + *der_len=max_len; result=asn1_der_coding(value,"",der,der_len,errorDescription); asn1_delete_structure(&value); result=asn1_write_value(crl,"tbsCertList.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len); @@ -257,6 +262,7 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len) result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value); result=asn1_write_value(value,"","printableString",1); result=asn1_write_value(value,"printableString","nist",4); + *der_len=max_len; result=asn1_der_coding(value,"",der,der_len,errorDescription); asn1_delete_structure(&value); result=asn1_write_value(crl,"tbsCertList.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len); @@ -298,6 +304,7 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len) result=asn1_write_value(crl,"signatureAlgorithm.parameters",NULL,0); /* NO OPTION */ /* signature */ + *der_len=max_len; result=asn1_der_coding(crl,"tbsCertList",der,der_len,errorDescription); if(result!=ASN1_SUCCESS){ printf("\n'tbsCertList' encoding creation: ERROR\n"); @@ -313,7 +320,7 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len) asn1_visit_tree(crl,""); printf("-----------------\n"); */ - + *der_len=max_len; result=asn1_der_coding(crl,"",der,der_len,errorDescription); if(result!=ASN1_SUCCESS){ printf("\n'crl1' encoding creation: ERROR\n"); @@ -424,7 +431,7 @@ main(int argc,char *argv[]) asn1_visit_tree(cert_def,"PKIX1Implicit88"); printf("-----------------\n"); */ - + der_len=1024; create_CRL(PKIX1Implicit88,der,&der_len); diff --git a/asn1/src/asn1Coding.c b/asn1/src/asn1Coding.c index 26883320..0480c779 100644 --- a/asn1/src/asn1Coding.c +++ b/asn1/src/asn1Coding.c @@ -286,6 +286,7 @@ main(int argc,char *argv[]) printf("\n"); asn1_print_structure(stdout,structure,"",ASN1_PRINT_NAME_TYPE_VALUE); + der_len=1024; asn1_result=asn1_der_coding(structure,"",der,&der_len, errorDescription); printf("\nCoding: %s\n\n",libtasn1_strerror(asn1_result)); diff --git a/asn1/tests/Test_parser.asn b/asn1/tests/Test_parser.asn index 8290dc75..e9b0ce9a 100644 --- a/asn1/tests/Test_parser.asn +++ b/asn1/tests/Test_parser.asn @@ -16,6 +16,11 @@ Sequence1 ::= SEQUENCE{ generic GeneralString } +OidTest ::= SEQUENCE{ + oid1 OBJECT IDENTIFIER DEFAULT Oid-type1 +} + +Oid-type1 OBJECT IDENTIFIER ::= {1 2 3 4} END @@ -27,3 +32,6 @@ END + + + diff --git a/asn1/tests/Test_parser.c b/asn1/tests/Test_parser.c index 87c1ee27..5d6b6381 100644 --- a/asn1/tests/Test_parser.c +++ b/asn1/tests/Test_parser.c @@ -84,6 +84,16 @@ test_type test_array[]={ {16," generic generalstring", ASN1_IDENTIFIER_NOT_FOUND,_FILE_":: identifier 'generalstring' not found"}, + /* Test: OID */ + {20," oid1 OBJECT IDENTIFIER DEFAULT Oid-type", + ASN1_IDENTIFIER_NOT_FOUND,_FILE_":: identifier 'Oid-type' not found"}, + {20," oid1 OBJECT IDENTIFIER DEFAULT 1", + ASN1_IDENTIFIER_NOT_FOUND,_FILE_":: identifier '1' not found"}, + {20," oid1 OBJECT IDENTIFIER DEFAULT", + ASN1_SYNTAX_ERROR,_FILE_":21: parse error near '}'"}, + {20," oid1 OBJECT IDENTIFIER DEFAULT Oid-type1", + ASN1_SUCCESS,""}, + /* end */ {0} diff --git a/asn1/tests/Test_tree.asn b/asn1/tests/Test_tree.asn index 7c368222..a9184562 100644 --- a/asn1/tests/Test_tree.asn +++ b/asn1/tests/Test_tree.asn @@ -9,6 +9,26 @@ DEFINITIONS IMPLICIT TAGS ::= BEGIN +OidTest ::= SEQUENCE{ + oid3 [3] OBJECT IDENTIFIER DEFAULT id-Test, + oid [1] OBJECT IDENTIFIER DEFAULT id-anyTest2, + oid2 [2] OBJECT IDENTIFIER DEFAULT id-anyTest +} + +OidAndTimeTest ::= SEQUENCE{ + set SET OF INTEGER, + oid OBJECT IDENTIFIER, + time2 GeneralizedTime, + bol BOOLEAN, + oct OCTET STRING, + bit BIT STRING OPTIONAL, + bol2 BOOLEAN DEFAULT TRUE, + enum ENUMERATED {v1(1),v2(2)} DEFAULT v1, + any [1] ANY OPTIONAL, + gen GeneralString OPTIONAL, + time1 UTCTime +} + SequenceTestTag ::= SEQUENCE{ int1 [2] EXPLICIT INTEGER, int2 [3] IMPLICIT INTEGER, @@ -19,7 +39,7 @@ SequenceTestTag ::= SEQUENCE{ Sequence1 ::= SEQUENCE{ - int1 [0] INTEGER DEFAULT -5, + int1 [0] INTEGER {v1(0),v2(1),v3(2)} DEFAULT v2, int2 INTEGER, seq SET OF INTEGER, id OBJECT IDENTIFIER, diff --git a/asn1/tests/Test_tree.c b/asn1/tests/Test_tree.c index b810c06e..0252ffd5 100644 --- a/asn1/tests/Test_tree.c +++ b/asn1/tests/Test_tree.c @@ -52,6 +52,8 @@ #define ACT_READ_DEFINITIONS 14 #define ACT_READ_TAG_CLASS 15 #define ACT_OID_2_STRUCTURE 16 +#define ACT_READ_LENGTH 17 +#define ACT_ENCODING_LENGTH 18 typedef struct{ @@ -67,6 +69,63 @@ test_type test_array[]={ {ACT_DELETE,"","",0,ASN1_ELEMENT_NOT_FOUND}, + /* Test: OID */ + {ACT_CREATE,"TEST_TREE.OidTest",0,0,ASN1_SUCCESS}, + {ACT_READ_LENGTH,"oid",NULL,9,ASN1_MEM_ERROR}, + {ACT_READ,"oid","2.5.29.2",9,ASN1_SUCCESS}, + {ACT_WRITE,"oid","1.2.3.4",0,ASN1_SUCCESS}, + {ACT_WRITE,"oid2","2.5.29.1",0,ASN1_SUCCESS}, + {ACT_WRITE,"oid3","1.2.29.2",0,ASN1_SUCCESS}, + {ACT_ENCODING_LENGTH,"",0,7,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,6,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,7,ASN1_SUCCESS}, + {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, + {ACT_DELETE,"","",0,ASN1_SUCCESS}, + {ACT_CREATE,"TEST_TREE.OidTest",0,0,ASN1_SUCCESS}, + {ACT_DECODING,0,0,0,ASN1_SUCCESS}, + {ACT_DECODING_START_END,"oid","START",2,ASN1_SUCCESS}, + {ACT_DECODING_START_END,"oid","END",6,ASN1_SUCCESS}, + {ACT_DECODING_START_END,"","START",0,ASN1_SUCCESS}, + {ACT_DECODING_START_END,"","END",6,ASN1_SUCCESS}, + {ACT_READ,"oid2","2.5.29.1",9,ASN1_SUCCESS}, + {ACT_READ,"oid3","1.2.29.2",9,ASN1_SUCCESS}, + {ACT_WRITE,"oid","1.2.3.4",0,ASN1_SUCCESS}, + {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, + {ACT_DELETE,"","",0,ASN1_SUCCESS}, + + /* Test: ENCODING_LENGTH and READ_LEN */ + {ACT_CREATE,"TEST_TREE.OidAndTimeTest",0,0,ASN1_SUCCESS}, + {ACT_WRITE,"oid","1.2.3.4",0,ASN1_SUCCESS}, + {ACT_WRITE,"time1","9801011200Z",1,ASN1_SUCCESS}, + {ACT_WRITE,"time2","2001010112001.12-0700",1,ASN1_SUCCESS}, + {ACT_WRITE,"oct","ABCD",4,ASN1_SUCCESS}, + {ACT_WRITE,"bol","TRUE",1,ASN1_SUCCESS}, + {ACT_WRITE,"enum","2",0,ASN1_SUCCESS}, + {ACT_WRITE,"bit","1\xC0",10,ASN1_SUCCESS}, + {ACT_WRITE,"any","\x30\x01\x01",3,ASN1_SUCCESS}, + {ACT_WRITE,"set","NEW",0,ASN1_SUCCESS}, + {ACT_WRITE,"set.?LAST","10",0,ASN1_SUCCESS}, + {ACT_WRITE,"set","NEW",0,ASN1_SUCCESS}, + {ACT_WRITE,"set.?LAST","1",0,ASN1_SUCCESS}, + {ACT_WRITE,"gen","Prova",5,ASN1_SUCCESS}, + {ACT_READ_LENGTH,"oid",NULL,8,ASN1_MEM_ERROR}, + {ACT_READ_LENGTH,"time1",NULL,12,ASN1_MEM_ERROR}, + {ACT_READ_LENGTH,"time2",NULL,22,ASN1_MEM_ERROR}, + {ACT_READ_LENGTH,"oct",NULL,4,ASN1_MEM_ERROR}, + {ACT_READ_LENGTH,"bol",NULL,5,ASN1_MEM_ERROR}, + {ACT_READ_LENGTH,"enum",NULL,1,ASN1_MEM_ERROR}, + {ACT_READ_LENGTH,"any",NULL,3,ASN1_MEM_ERROR}, + {ACT_READ_LENGTH,"gen",NULL,5,ASN1_MEM_ERROR}, + {ACT_ENCODING_LENGTH,"",0,79,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,78,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,79,ASN1_SUCCESS}, + {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, + {ACT_DELETE,"","",0,ASN1_SUCCESS}, + {ACT_CREATE,"TEST_TREE.OidAndTimeTest",0,0,ASN1_SUCCESS}, + {ACT_DECODING,0,0,0,ASN1_SUCCESS}, + {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, + {ACT_DELETE,"","",0,ASN1_SUCCESS}, + /* Test: OID to STRUCTURE */ {ACT_OID_2_STRUCTURE,"2.5.29.3","",0,ASN1_ELEMENT_NOT_FOUND}, {ACT_OID_2_STRUCTURE,"1.2.29.2","",0,ASN1_ELEMENT_NOT_FOUND}, @@ -88,17 +147,21 @@ test_type test_array[]={ {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_DELETE,"","",0,ASN1_SUCCESS}, - /* Test: OBJECT IDENTIFIER elements */ {ACT_CREATE,"TEST_TREE.Sequence1",0,0,ASN1_SUCCESS}, + {ACT_WRITE,"int1","v2",0,ASN1_SUCCESS}, + {ACT_READ,"int1","\x01",1,ASN1_SUCCESS}, {ACT_WRITE,"int2","0",0,ASN1_SUCCESS}, {ACT_WRITE,"oct","\x02\x01\x0a",3,ASN1_SUCCESS}, {ACT_WRITE,"id","1 2 3 4 5",0,ASN1_VALUE_NOT_VALID}, {ACT_WRITE,"id","2.5.29.2",0,ASN1_SUCCESS}, {ACT_READ,"id","2.5.29.2",9,ASN1_SUCCESS}, + {ACT_READ_LENGTH,"id",NULL,9,ASN1_MEM_ERROR}, {ACT_WRITE,"any1","\x02\x01\x05",3,ASN1_SUCCESS}, {ACT_READ_DEFINITIONS,"TEST_TREE.id-anyTest","2.5.29.1",9,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING_LENGTH,"",0,20,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,19,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,200,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_DELETE,"","",0,ASN1_SUCCESS}, {ACT_CREATE,"TEST_TREE.Sequence1",0,0,ASN1_SUCCESS}, @@ -115,61 +178,67 @@ test_type test_array[]={ {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_WRITE,"","teletexString",0,ASN1_SUCCESS}, {ACT_WRITE,"teletexString","PROVA",5,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING_LENGTH,"",0,7,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,6,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,7,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_DELETE,"","",0,ASN1_SUCCESS}, {ACT_CREATE,"TEST_TREE.X520LocalityName",0,0,ASN1_SUCCESS}, {ACT_DECODING,0,0,0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_DELETE,"","",0,ASN1_SUCCESS}, - + /* Test: OPTIONAL elements */ {ACT_CREATE,"TEST_TREE.DHParameter",0,0,ASN1_SUCCESS}, {ACT_WRITE,"prime","1",0,ASN1_SUCCESS}, {ACT_WRITE,"base","2",0,ASN1_SUCCESS}, {ACT_WRITE,"privateValueLength",NULL,0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING_LENGTH,"",0,8,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,7,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,8,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_DELETE,"","",0,ASN1_SUCCESS}, {ACT_CREATE,"TEST_TREE.DHParameter",0,0,ASN1_SUCCESS}, {ACT_DECODING,0,0,0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_DELETE,"","",0,ASN1_SUCCESS}, - + /* Test: Integer */ {ACT_CREATE,"TEST_TREE.AnyTest2",0,0,ASN1_SUCCESS}, {ACT_WRITE,"","int",0,ASN1_SUCCESS}, {ACT_WRITE,"int","0",0,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING_LENGTH,"",0,3,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,2,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,3,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_WRITE,"int","-1",0,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING,"",0,1024,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_WRITE,"int","1",0,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING,"",0,1024,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_WRITE,"int","2000000000",0,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING,"",0,1024,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_WRITE,"int","-2000000000",0,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING,"",0,1024,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_WRITE,"int","-20000000000",0,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING,"",0,1024,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_WRITE,"int","20000000000",0,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING,"",0,1024,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_DELETE,"","",0,ASN1_SUCCESS}, - + /* Test: elements without names */ {ACT_CREATE,"TEST_TREE.Sequence1",0,0,ASN1_SUCCESS}, {ACT_WRITE,"int2","10",0,ASN1_SUCCESS}, @@ -181,37 +250,44 @@ test_type test_array[]={ {ACT_NUMBER_OF_ELEMENTS,"seq","",2,ASN1_SUCCESS}, {ACT_WRITE,"id","1.2.3.4",0,ASN1_SUCCESS}, {ACT_WRITE,"oct","\x30\x03\x02\x01\x15",5,ASN1_SUCCESS}, - {ACT_ENCODING,"int2",0,0,ASN1_SUCCESS}, + {ACT_ENCODING,"int2",0,1024,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, - {ACT_ENCODING,"seq.?2",0,0,ASN1_SUCCESS}, + {ACT_ENCODING,"seq.?2",0,2,ASN1_MEM_ERROR}, + {ACT_ENCODING,"seq.?2",0,3,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING_LENGTH,"",0,25,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,24,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,25,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_CREATE,"TEST_TREE.Sequence1",0,0,ASN1_SUCCESS}, {ACT_DECODING_ELEMENT,"int2",0,0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_READ,"int2","\x0a",1,ASN1_SUCCESS}, + {ACT_READ_LENGTH,"int2",NULL,1,ASN1_MEM_ERROR}, {ACT_CREATE,"TEST_TREE.Sequence1",0,0,ASN1_SUCCESS}, {ACT_DECODING,0,0,0,ASN1_SUCCESS}, {ACT_DECODING_START_END,"seq.?2","START",10,ASN1_SUCCESS}, {ACT_EXPAND_OCTET,"oct","id",0,ASN1_SUCCESS}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_DELETE,"","",0,ASN1_SUCCESS}, - + /* Test GeneralString */ {ACT_CREATE,"TEST_TREE.Test3",0,0,ASN1_SUCCESS}, {ACT_WRITE,"a","1234",0,ASN1_SUCCESS}, {ACT_WRITE,"b","prova",5,ASN1_SUCCESS}, - {ACT_ENCODING,"",0,0,ASN1_SUCCESS}, + {ACT_ENCODING_LENGTH,"",0,17,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,16,ASN1_MEM_ERROR}, + {ACT_ENCODING,"",0,17,ASN1_SUCCESS}, {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS}, {ACT_DELETE,"","",0,ASN1_SUCCESS}, {ACT_CREATE,"TEST_TREE.Test3",0,0,ASN1_SUCCESS}, {ACT_DECODING,0,0,0,ASN1_SUCCESS}, {ACT_DECODING_ELEMENT,"b",0,0,ASN1_SUCCESS}, {ACT_READ,"b","prova",5,ASN1_SUCCESS}, + {ACT_READ_LENGTH,"b",NULL,5,ASN1_MEM_ERROR}, {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS}, {ACT_DELETE,"","",0,ASN1_SUCCESS}, - + /* end */ @@ -234,11 +310,16 @@ main(int argc,char *argv[]) int valueLen,tag=0,class=0; int k; int start,end; + const char *str_p=NULL; printf("\n\n/****************************************/\n"); printf( "/* Test sequence : Test_tree */\n"); printf( "/****************************************/\n\n"); + /* Check version */ + if(asn1_check_version("0.2.4")==NULL) + printf("\nLibrary version check ERROR:\n actual version: %s\n\n",asn1_check_version(NULL)); + if(1) result=asn1_parser2tree("Test_tree.asn",&definitions,errorDescription); else @@ -284,9 +365,13 @@ main(int argc,char *argv[]) result=asn1_write_value(asn1_element,test->par1,test->par2,test->par3); break; case ACT_READ: - valueLen=1024; + valueLen=test->par3; result=asn1_read_value(asn1_element,test->par1,value,&valueLen); break; + case ACT_READ_LENGTH: + valueLen=0; + result=asn1_read_value(asn1_element,test->par1,NULL,&valueLen); + break; case ACT_READ_DEFINITIONS: valueLen=1024; result=asn1_read_value(definitions,test->par1,value,&valueLen); @@ -295,9 +380,15 @@ main(int argc,char *argv[]) result=asn1_read_tag(asn1_element,test->par1,&tag,&class); break; case ACT_ENCODING: + der_len=test->par3; result=asn1_der_coding(asn1_element,test->par1,der,&der_len, errorDescription); break; + case ACT_ENCODING_LENGTH: + der_len=0; + result=asn1_der_coding(asn1_element,test->par1,NULL,&der_len, + errorDescription); + break; case ACT_DECODING: result=asn1_der_decoding(&asn1_element,der,der_len, errorDescription); @@ -318,7 +409,7 @@ main(int argc,char *argv[]) test->par2); break; case ACT_OID_2_STRUCTURE: - result=asn1_find_structure_from_oid(definitions,test->par1,value); + str_p=asn1_find_structure_from_oid(definitions,test->par1); break; case ACT_VISIT: asn1_print_structure(out,asn1_element,test->par1,test->par3); @@ -372,6 +463,7 @@ main(int argc,char *argv[]) } break; case ACT_NUMBER_OF_ELEMENTS: + case ACT_READ_LENGTH: if((result != test->errorNumber) || (valueLen != test->par3)){ errorCounter++; @@ -379,20 +471,31 @@ main(int argc,char *argv[]) printf(" Action %d - %s\n",test->action,test->par1); printf(" Error expected: %s - %d\n",libtasn1_strerror(test->errorNumber), test->par3); - printf("\n Error detected: %s - %d\n\n",libtasn1_strerror(result), + printf(" Error detected: %s - %d\n\n",libtasn1_strerror(result), valueLen); } break; - case ACT_OID_2_STRUCTURE: + case ACT_ENCODING_LENGTH: if((result != test->errorNumber) || - ((result == ASN1_SUCCESS) && (strcmp(value,test->par2)))){ + (der_len != test->par3)){ + errorCounter++; + printf("ERROR N. %d:\n",errorCounter); + printf(" Action %d - %s\n",test->action,test->par1); + printf(" Error expected: %s - %d\n",libtasn1_strerror(test->errorNumber), + test->par3); + printf(" Error detected: %s - %d\n\n",libtasn1_strerror(result), + der_len); + } + break; + case ACT_OID_2_STRUCTURE: + if(((test->errorNumber!=ASN1_SUCCESS) && (str_p!=NULL)) || + ((test->errorNumber==ASN1_SUCCESS) && (str_p==NULL)) || + ((test->errorNumber==ASN1_SUCCESS) && (strcmp(str_p,test->par2)))){ errorCounter++; printf("ERROR N. %d:\n",errorCounter); printf(" Action %d - %s\n",test->action,test->par1); - printf(" Error expected: %s - %s\n",libtasn1_strerror(test->errorNumber), - test->par2); - printf("\n Error detected: %s - %s\n\n",libtasn1_strerror(result), - value); + printf(" Error expected: %s - %s\n",libtasn1_strerror(test->errorNumber),test->par2); + printf(" Value detected: %s\n\n",str_p); } break; case ACT_DECODING_START_END: diff --git a/asn1/tests/Test_tree_asn1_tab.c b/asn1/tests/Test_tree_asn1_tab.c index 6099e09b..e5d9c0f9 100644 --- a/asn1/tests/Test_tree_asn1_tab.c +++ b/asn1/tests/Test_tree_asn1_tab.c @@ -13,9 +13,116 @@ const ASN1_ARRAY_TYPE Test_tree_asn1_tab[]={ {"pkix",1073741825,"7"}, {"id-mod",1073741825,"0"}, {"id-pkix1-implicit-88",1,"2"}, - {"Sequence1",536870917,0}, - {"int1",1610645507,0}, - {0,9,"-5"}, - {"int2",3,0}, + {"OidTest",1610612741,0}, + {"oid3",1610653708,0}, + {0,1073741833,"id-Test"}, + {0,4104,"3"}, + {"oid",1610653708,0}, + {0,1073741833,"id-anyTest2"}, + {0,4104,"1"}, + {"oid2",536911884,0}, + {0,1073741833,"id-anyTest"}, + {0,4104,"2"}, + {"OidAndTimeTest",1610612741,0}, + {"set",1610612751,0}, + {0,3,0}, + {"oid",1073741836,0}, + {"time2",1082130449,0}, + {"bol",1073741828,0}, + {"oct",1073741831,0}, + {"bit",1073758214,0}, + {"bol2",1610645508,0}, + {0,65545,0}, + {"enum",1610907669,0}, + {0,1073741833,"v1"}, + {"v1",1073741825,"1"}, + {"v2",1,"2"}, + {"any",1610637325,0}, + {0,4104,"1"}, + {"gen",1073758235,0}, + {"time1",16777233,0}, + {"SequenceTestTag",1610612741,0}, + {"int1",1610620931,0}, + {0,2056,"2"}, + {"int2",1610620931,0}, + {0,4104,"3"}, + {"str1",1610620930,"PrintableString"}, + {0,4104,"1"}, + {"str2",1073741826,"UniversalString"}, + {"str3",536879106,"UniversalString"}, + {0,2056,"2"}, + {"Sequence1",1610612741,0}, + {"int1",1610915843,0}, + {0,1073741833,"v2"}, + {0,1073745928,"0"}, + {"v1",1073741825,"0"}, + {"v2",1073741825,"1"}, + {"v3",1,"2"}, + {"int2",1073741827,0}, + {"seq",1610612751,0}, + {0,3,0}, + {"id",1073741836,0}, + {"oct",1073741831,0}, + {"any1",541081613,0}, + {"id",1,0}, + {"DHParameter",1610612741,0}, + {"prime",1073741827,0}, + {"base",1073741827,0}, + {"privateValueLength",16387,0}, + {"id-octetTest1",1879048204,0}, + {0,1073741825,"1"}, + {0,1073741825,"2"}, + {0,1073741825,"3"}, + {0,1,"4"}, + {"Sequence_octetTest1",1610612741,0}, + {"int",3,0}, + {"AnyTest2",1610612754,0}, + {"str",1073741831,0}, + {"int",3,0}, + {"id-ic",1879048204,0}, + {0,1073741825,"2"}, + {0,1,"5"}, + {"id-anyTest",1879048204,0}, + {0,1073741825,"id-ic"}, + {0,1073741825,"29"}, + {0,1,"1"}, + {"id-anyTest2",1879048204,0}, + {0,1073741825,"id-ic"}, + {0,1073741825,"29"}, + {0,1,"2"}, + {"anyTest2",1073741827,0}, + {"VisibleString",1610620935,0}, + {0,4360,"26"}, + {"NumericString",1610620935,0}, + {0,4360,"18"}, + {"IA5String",1610620935,0}, + {0,4360,"22"}, + {"TeletexString",1610620935,0}, + {0,4360,"20"}, + {"PrintableString",1610620935,0}, + {0,4360,"19"}, + {"UniversalString",1610620935,0}, + {0,4360,"28"}, + {"BMPString",1610620935,0}, + {0,4360,"30"}, + {"UTF8String",1610620935,0}, + {0,4360,"12"}, + {"Test3",1610612741,0}, + {"a",1073741827,0}, + {"b",536879106,"GeneralString2"}, + {0,2056,"1"}, + {"GeneralString2",1610620955,0}, + {0,2056,"2"}, + {"X520LocalityName",1610612754,0}, + {"teletexString",1073741826,"TeletexString"}, + {"printableString",1073741826,"PrintableString"}, + {"universalString",1073741826,"UniversalString"}, + {"utf8String",1073741826,"UTF8String"}, + {"bmpString",2,"BMPString"}, + {"id-Test",805306380,0}, + {0,1073741825,"1"}, + {0,1073741825,"2"}, + {0,1073741825,"29"}, + {0,1,"2"}, {0,0,0} }; diff --git a/crypto/AUTHORS b/crypto/AUTHORS index b152e1b0..faa5da8a 100644 --- a/crypto/AUTHORS +++ b/crypto/AUTHORS @@ -50,7 +50,7 @@ Assigns past and future changes. twoaday@freakmail.de LIBGCRYPT Simon Josefsson 2002-10-25 -Assigns past and future changes to FSF (cipher/{md4,crc}.c, CTS flag, +Assigns past and future changes to FSF (cipher/{md4,crc}.c, CTS/MAC flags, self test improvements) simon@josefsson.org @@ -72,7 +72,7 @@ files from Cryptlib. Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. - Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/crypto/ChangeLog b/crypto/ChangeLog index 7e3acd80..3a48a46d 100644 --- a/crypto/ChangeLog +++ b/crypto/ChangeLog @@ -1,3 +1,16 @@ +2003-03-24 Moritz Schulte + + * NEWS: Mention new CBC_MAC flag. + + * AUTHORS (Maintainer): Update entry for Simon Josefsson. + +2003-03-04 Moritz Schulte + + * TODO: Remove item about resetting handles, since + gcry_cipher_reset is implemented by now. + + * NEWS: Mentioned gcry_cipher_reset. + 2003-01-21 Werner Koch * README (Configure options): New. diff --git a/crypto/NEWS b/crypto/NEWS index 5b22bf0d..a255a849 100644 --- a/crypto/NEWS +++ b/crypto/NEWS @@ -8,9 +8,20 @@ Noteworthy changes in version 1.1.13 (unreleased) * The public RSA exponent can now be specified in key generation. + * The random module won't print the "not enough random bytes + available" anymore. A new progress status is issued instead. + + * CBC-MAC for block ciphers is now supported, by using a + GCRY_CIPHER_CBC_MAC cipher flag. + + * RSA blinding is now supported and is used automatically for RSA + decryption. It can be explicitely disabled by using the `no-blinding' + symbol in the `flags' s-exp. + * Interface changes relative to the 1.1.12 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcry_pk_decrypt ENHANCED: Allows flag to return complete S-expression. +gcry_cipher_reset NEW ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Noteworthy changes in version 1.1.12 (2003-01-20) diff --git a/crypto/THANKS b/crypto/THANKS index 00fc768d..cbfe5520 100644 --- a/crypto/THANKS +++ b/crypto/THANKS @@ -39,6 +39,7 @@ Hendrik Buschkamp buschkamp@rheumanet.org Holger Schurig holger@d.om.org Hugh Daniel hugh@toad.com Ian McKellar imckellar@harvestroad.com.au +Ian Peters itp@ximian.com Janusz A. Urbanowicz alex@bofh.torun.pl James Troup james@nocrew.org Jean-loup Gailly gzip@prep.ai.mit.edu diff --git a/crypto/TODO b/crypto/TODO index 969c3b69..66cdc23e 100644 --- a/crypto/TODO +++ b/crypto/TODO @@ -1,9 +1,5 @@ * Run w32-dll/build-def when we introduce a new fucntion. -* switching from encrypt to decrypt requires a close and open. - Wouldn't it be better if we have a reset function or integrate that - with setkey? - * add more tests. Even basic is very minimal. * udiv-qrnbd.o should get build as *.lo [HPUX] @@ -22,3 +18,5 @@ * Make use of the forthcoming visibility attribute. * Add attributes to the MPI functions. + +* Write tests for the progress function \ No newline at end of file diff --git a/crypto/cipher/ChangeLog b/crypto/cipher/ChangeLog index 6f7dfa70..3f00e2da 100644 --- a/crypto/cipher/ChangeLog +++ b/crypto/cipher/ChangeLog @@ -1,3 +1,114 @@ +2003-03-26 Moritz Schulte + + * dynload.c (_gcry_enum_gnupgext_pubkeys): Adjust `encrypt' and + `decrypt' function arguments. + (_gcry_enum_gnupgext_pubkeys): Likewise. + * dynload.h: Likewise. + + * pubkey.c (dummy_decrypt): Add argument: int flags. + (dummy_encrypt): Likewise. + + * elgamal.c (_gcry_elg_encrypt): Add argument: int flags. + (_gcry_elg_decrypt): Likewise. + + * rsa.c (_gcry_rsa_encrypt): Add argument: int flags. + (_gcry_rsa_decrypt): Likewise. + + * pubkey.c: Add `flags' argument to members `encrypt' and + `decrypt' of struct `pubkey_table_s'. + + * rsa.h: Add `flags' argument to function declarations. + * elgamal.h: Likewise. + + * pubkey.c (sexp_data_to_mpi): New variable: int parsed_flags. + (sexp_data_to_mpi): Set `parsed_flags'. + (sexp_data_to_mpi): New argument: int *flags. + (gcry_pk_encrypt): New variable: int flags. + (gcry_pk_encrypt): Pass `flags' to pubkey_encrypt. + (pubkey_encrypt): New variable: int flags. + (pubkey_encrypt): Pass `flags' to pubkey encrypt function. + (pubkey_decrypt): Likewise. + (pubkey_decrypt): Pass `flags' to pubkey encrypt function. + (gcry_pk_encrypt): Include `flags' s-exp in return list. + (sexp_to_enc): New argument: int *flags. + (gcry_pk_decrypt): New variable: int flags. + (gcry_pk_decrypt): Pass `flags' to pubkey_decrypt. + (sexp_to_enc): New variable: int parsed_flags. + (sexp_to_enc): Set `parsed_flags'. + +2003-03-22 Simon Josefsson + + * cipher.c (gcry_cipher_open, do_cbc_encrypt) + (gcry_cipher_encrypt): Support GCRY_CIPHER_CBC_MAC. + (gcry_cipher_ctl): Support GCRYCTL_SET_CBC_MAC. + +2003-03-19 Werner Koch + + * primegen.c (gen_prime): New args EXTRA_CHECK and EXTRA_CHECK_ARG + to allow for a user callback. Changed all callers. + (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Ditto, pass them to gen_prime. + * rsa.c (check_exponent): New. + (generate): Use a callback to ensure that a given exponent is + actually generated. + +2003-03-12 Moritz Schulte + + * primegen.c: Initialize `no_of_small_prime_numbers' statically. + (gen_prime): Remove calculation of `no_of_small_prime_numbers'. + +2003-03-03 Moritz Schulte + + * md.c (gcry_md_ctl): Rewritten to use same style like the other + functions dispatchers. + +2003-03-02 Moritz Schulte + + * cipher.c (struct gcry_cipher_handle): New member: algo_index. + (gcry_cipher_open): Allocate memory for two cipher contexts. + Initialize algo_index. + (cipher_setkey): Duplicate context into reserved memory. + (cipher_reset): New function, which resets the context and clear + the IV. + (gcry_cipher_ctl): Call cipher_reset. + +2003-02-23 Moritz Schulte + + * cipher.c: Remove (bogus) `digitp' macro definition. + * md.c: Likewise. + + * blowfish.c (burn_stack): Removed. + * arcfour.c (burn_stack): Likewise. + * cast5.c (burn_stack): Likewise. + * des.c (burn_stack): Likewise. + * md4.c (burn_stack): Likewise. + * md5.c (burn_stack): Likewise. + * random.c (burn_stack): Likewise. + * rijndael.c (burn_stack): Likewise. + * rmd160.c (burn_stack): Likewise. + * sha1.c (burn_stack): Likewise. + * sha256.c (burn_stack): Likewise. + * tiger.c (burn_stack): Likewise. + * twofish.c (burn_stack): Likewise. + + * blowfish.c: Changed all occurences of burn_stack to + _gcry_burn_stack. + * arcfour.c: Likewise. + * cast5.c: Likewise. + * des.c: Likewise. + * md4.c: Likewise. + * md5.c: Likewise. + * random.c: Likewise. + * rijndael.c: Likewise. + * rmd160.c: Likewise. + * sha1.c: Likewise. + * sha256.c: Likewise. + * tiger.c: Likewise. + * twofish.c: Likewise. + + * arcfour.c (_gcry_arcfour_get_info): Use GCRY_CIPHER_ARCFOUR + instead of hard-coded value `301'. + 2003-01-24 Werner Koch * random.c (_gcry_register_random_progress): New. diff --git a/crypto/cipher/arcfour.c b/crypto/cipher/arcfour.c index 66017b08..702d0a75 100644 --- a/crypto/cipher/arcfour.c +++ b/crypto/cipher/arcfour.c @@ -1,5 +1,5 @@ /* arcfour.c - The arcfour stream cipher - * Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -41,18 +41,6 @@ typedef struct { static void -burn_stack (int bytes) -{ - char buf[64]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - -static void do_encrypt_stream( ARCFOUR_context *ctx, byte *outbuf, const byte *inbuf, unsigned int length ) { @@ -81,7 +69,7 @@ encrypt_stream( ARCFOUR_context *ctx, { do_encrypt_stream (ctx, outbuf, inbuf, length ); - burn_stack (64); + _gcry_burn_stack (64); } @@ -126,7 +114,7 @@ static int arcfour_setkey ( ARCFOUR_context *ctx, const byte *key, unsigned int keylen ) { int rc = do_arcfour_setkey (ctx, key, keylen ); - burn_stack (300); + _gcry_burn_stack (300); return rc; } @@ -188,7 +176,7 @@ _gcry_arcfour_get_info( int algo, size_t *keylen, size_t *blocksize, = encrypt_stream; - if( algo == 301 ) + if( algo == GCRY_CIPHER_ARCFOUR ) return "ARCFOUR"; return NULL; } diff --git a/crypto/cipher/blowfish.c b/crypto/cipher/blowfish.c index af4f4978..a911c5b3 100644 --- a/crypto/cipher/blowfish.c +++ b/crypto/cipher/blowfish.c @@ -1,5 +1,5 @@ /* blowfish.c - Blowfish encryption - * Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -282,18 +282,6 @@ function_F( BLOWFISH_context *bc, u32 x ) #define R(l,r,i) do { l ^= p[i]; r ^= F(l); } while(0) static void -burn_stack (int bytes) -{ - char buf[64]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - -static void do_encrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) { #if BLOWFISH_ROUNDS == 16 @@ -448,7 +436,7 @@ static void encrypt_block ( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) { do_encrypt_block (bc, outbuf, inbuf); - burn_stack (64); + _gcry_burn_stack (64); } @@ -474,7 +462,7 @@ static void decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) { do_decrypt_block (bc, outbuf, inbuf); - burn_stack (64); + _gcry_burn_stack (64); } @@ -596,7 +584,7 @@ static int bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) { int rc = do_bf_setkey (c, key, keylen); - burn_stack (64); + _gcry_burn_stack (64); return rc; } diff --git a/crypto/cipher/cast5.c b/crypto/cipher/cast5.c index fbed819e..e3788541 100644 --- a/crypto/cipher/cast5.c +++ b/crypto/cipher/cast5.c @@ -1,5 +1,5 @@ /* cast5.c - CAST5 cipher (RFC2144) - * Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -358,18 +358,6 @@ rol(int n, u32 x) (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) ) static void -burn_stack (int bytes) -{ - char buf[64]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - -static void do_encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) { u32 l, r, t; @@ -427,7 +415,7 @@ static void encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) { do_encrypt_block (c, outbuf, inbuf); - burn_stack (20+4*sizeof(void*)); + _gcry_burn_stack (20+4*sizeof(void*)); } @@ -477,7 +465,7 @@ static void decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) { do_decrypt_block (c, outbuf, inbuf); - burn_stack (20+4*sizeof(void*)); + _gcry_burn_stack (20+4*sizeof(void*)); } @@ -624,7 +612,7 @@ static int cast_setkey( CAST5_context *c, byte *key, unsigned keylen ) { int rc = do_cast_setkey (c, key, keylen); - burn_stack (96+7*sizeof(void*)); + _gcry_burn_stack (96+7*sizeof(void*)); return rc; } diff --git a/crypto/cipher/cipher.c b/crypto/cipher/cipher.c index 3aff308f..beaa788a 100644 --- a/crypto/cipher/cipher.c +++ b/crypto/cipher/cipher.c @@ -38,8 +38,6 @@ #define CTX_MAGIC_NORMAL 0x24091964 #define CTX_MAGIC_SECURE 0x46919042 -#define digitp(p) (*(p) >= 0 && *(p) <= '9') - static struct { const char *oidstring; int algo; @@ -89,6 +87,7 @@ struct gcry_cipher_handle { int algo; int mode; unsigned int flags; + int algo_index; size_t blocksize; byte iv[MAX_BLOCKSIZE]; /* (this should be ulong aligned) */ byte lastiv[MAX_BLOCKSIZE]; @@ -517,7 +516,9 @@ gcry_cipher_open( int algo, int mode, unsigned int flags ) /* check flags */ if( (flags & ~(GCRY_CIPHER_SECURE| GCRY_CIPHER_ENABLE_SYNC| - GCRY_CIPHER_CBC_CTS)) ) { + GCRY_CIPHER_CBC_CTS| + GCRY_CIPHER_CBC_MAC)) || + (flags & GCRY_CIPHER_CBC_CTS & GCRY_CIPHER_CBC_MAC)) { set_lasterr( GCRYERR_INV_CIPHER_ALGO ); return NULL; } @@ -560,11 +561,14 @@ gcry_cipher_open( int algo, int mode, unsigned int flags ) /* ? perform selftest here and mark this with a flag in cipher_table ? */ - h = secure ? gcry_calloc_secure( 1, sizeof *h - + cipher_table[idx].contextsize - - sizeof(PROPERLY_ALIGNED_TYPE) ) - : gcry_calloc( 1, sizeof *h + cipher_table[idx].contextsize - - sizeof(PROPERLY_ALIGNED_TYPE) ); + h = secure ? gcry_calloc_secure( 1, + sizeof *h + + 2 * cipher_table[idx].contextsize + - sizeof (PROPERLY_ALIGNED_TYPE) ) + : gcry_calloc( 1, + sizeof *h + + 2 * cipher_table[idx].contextsize + - sizeof (PROPERLY_ALIGNED_TYPE) ); if( !h ) { set_lasterr( GCRYERR_NO_MEM ); return NULL; @@ -573,6 +577,7 @@ gcry_cipher_open( int algo, int mode, unsigned int flags ) h->algo = algo; h->mode = mode; h->flags = flags; + h->algo_index = idx; h->blocksize = cipher_table[idx].blocksize; h->setkey = cipher_table[idx].setkey; h->encrypt = cipher_table[idx].encrypt; @@ -600,7 +605,15 @@ gcry_cipher_close( GCRY_CIPHER_HD h ) static int cipher_setkey( GCRY_CIPHER_HD c, byte *key, unsigned keylen ) { - return (*c->setkey)( &c->context.c, key, keylen ); + int ret; + + ret = (*c->setkey)( &c->context.c, key, keylen ); + if (! ret) + memcpy ((void *) ((char *) &c->context.c + + cipher_table[c->algo_index].contextsize), + (void *) &c->context.c, + cipher_table[c->algo_index].contextsize); + return ret; } @@ -620,6 +633,17 @@ cipher_setiv( GCRY_CIPHER_HD c, const byte *iv, unsigned ivlen ) } +static void +cipher_reset (GCRY_CIPHER_HD c) +{ + memcpy ((void *) &c->context.c, + (void *) ((char *) &c->context.c + + cipher_table[c->algo_index].contextsize), + cipher_table[c->algo_index].contextsize); + memset (c->iv, 0, c->blocksize); + memset (c->lastiv, 0, c->blocksize); +} + static void do_ecb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks ) @@ -668,7 +692,8 @@ do_cbc_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nbyt (*c->encrypt)( &c->context.c, outbuf, outbuf ); memcpy(c->iv, outbuf, blocksize ); inbuf += c->blocksize; - outbuf += c->blocksize; + if (!(c->flags & GCRY_CIPHER_CBC_MAC)) + outbuf += c->blocksize; } if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) @@ -918,7 +943,7 @@ gcry_cipher_encrypt (GcryCipherHd h, byte *out, size_t outsize, } else { - if ( outsize < inlen ) + if ( outsize < ((h->flags & GCRY_CIPHER_CBC_MAC) ? h->blocksize : inlen)) rc = GCRYERR_TOO_SHORT; else if ((h->mode == GCRY_CIPHER_MODE_ECB || (h->mode == GCRY_CIPHER_MODE_CBC @@ -1044,16 +1069,30 @@ gcry_cipher_ctl( GCRY_CIPHER_HD h, int cmd, void *buffer, size_t buflen) case GCRYCTL_SET_IV: cipher_setiv( h, buffer, buflen ); break; + case GCRYCTL_RESET: + cipher_reset (h); + break; case GCRYCTL_CFB_SYNC: cipher_sync( h ); break; case GCRYCTL_SET_CBC_CTS: if (buflen) - h->flags |= GCRY_CIPHER_CBC_CTS; + if (h->flags & GCRY_CIPHER_CBC_MAC) + rc = GCRYERR_INV_FLAG; + else + h->flags |= GCRY_CIPHER_CBC_CTS; else h->flags &= ~GCRY_CIPHER_CBC_CTS; break; - + case GCRYCTL_SET_CBC_MAC: + if (buflen) + if (h->flags & GCRY_CIPHER_CBC_CTS) + rc = GCRYERR_INV_FLAG; + else + h->flags |= GCRY_CIPHER_CBC_MAC; + else + h->flags &= ~GCRY_CIPHER_CBC_MAC; + break; case GCRYCTL_DISABLE_ALGO: /* this one expects a NULL handle and buffer pointing to an * integer with the algo number. diff --git a/crypto/cipher/des.c b/crypto/cipher/des.c index bb196f4a..7ec86443 100644 --- a/crypto/cipher/des.c +++ b/crypto/cipher/des.c @@ -1,5 +1,5 @@ /* des.c - DES and Triple-DES encryption/decryption Algorithm - * Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -135,18 +135,6 @@ working_memcmp( const char *a, const char *b, size_t n ) } #endif -static void -burn_stack (int bytes) -{ - char buf[64]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - /* Some defines/checks to support standalone modules */ @@ -610,7 +598,7 @@ des_setkey (struct _des_ctx *ctx, const byte * key) return GCRYERR_SELFTEST; des_key_schedule (key, ctx->encrypt_subkeys); - burn_stack (32); + _gcry_burn_stack (32); for(i=0; i<32; i+=2) { @@ -669,7 +657,7 @@ tripledes_set2keys (struct _tripledes_ctx *ctx, des_key_schedule (key1, ctx->encrypt_subkeys); des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); - burn_stack (32); + _gcry_burn_stack (32); for(i=0; i<32; i+=2) { @@ -707,7 +695,7 @@ tripledes_set3keys (struct _tripledes_ctx *ctx, des_key_schedule (key1, ctx->encrypt_subkeys); des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); des_key_schedule (key3, &(ctx->encrypt_subkeys[64])); - burn_stack (32); + _gcry_burn_stack (32); for(i=0; i<32; i+=2) { @@ -1016,10 +1004,10 @@ do_tripledes_setkey ( struct _tripledes_ctx *ctx, byte *key, unsigned keylen ) tripledes_set3keys ( ctx, key, key+8, key+16); if( is_weak_key( key ) || is_weak_key( key+8 ) || is_weak_key( key+16 ) ) { - burn_stack (64); + _gcry_burn_stack (64); return GCRYERR_WEAK_KEY; } - burn_stack (64); + _gcry_burn_stack (64); return 0; } @@ -1029,14 +1017,14 @@ static void do_tripledes_encrypt( struct _tripledes_ctx *ctx, byte *outbuf, byte *inbuf ) { tripledes_ecb_encrypt ( ctx, inbuf, outbuf ); - burn_stack (32); + _gcry_burn_stack (32); } static void do_tripledes_decrypt( struct _tripledes_ctx *ctx, byte *outbuf, byte *inbuf ) { tripledes_ecb_decrypt ( ctx, inbuf, outbuf ); - burn_stack (32); + _gcry_burn_stack (32); } @@ -1053,10 +1041,10 @@ do_des_setkey ( struct _des_ctx *ctx, byte *key, unsigned keylen ) des_setkey (ctx, key); if( is_weak_key( key ) ) { - burn_stack (64); + _gcry_burn_stack (64); return GCRYERR_WEAK_KEY; } - burn_stack (64); + _gcry_burn_stack (64); return 0; } @@ -1066,14 +1054,14 @@ static void do_des_encrypt( struct _des_ctx *ctx, byte *outbuf, byte *inbuf ) { des_ecb_encrypt ( ctx, inbuf, outbuf ); - burn_stack (32); + _gcry_burn_stack (32); } static void do_des_decrypt( struct _des_ctx *ctx, byte *outbuf, byte *inbuf ) { des_ecb_decrypt ( ctx, inbuf, outbuf ); - burn_stack (32); + _gcry_burn_stack (32); } diff --git a/crypto/cipher/dynload.c b/crypto/cipher/dynload.c index 4f00a1e7..d386ea2a 100644 --- a/crypto/cipher/dynload.c +++ b/crypto/cipher/dynload.c @@ -221,8 +221,8 @@ _gcry_enum_gnupgext_pubkeys( void **enum_context, int *algo, int (**generate)( int algo, unsigned int nbits, unsigned long use_e, MPI *skey, MPI **retfactors ), int (**check_secret_key)( int algo, MPI *skey ), - int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey ), - int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey ), + int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey, int flags ), + int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey, int flags ), int (**sign)( int algo, MPI *resarr, MPI data, MPI *skey ), int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey, int (*cmp)(void *, MPI), void *opaquev ), @@ -234,8 +234,8 @@ _gcry_enum_gnupgext_pubkeys( void **enum_context, int *algo, int (**)( int, unsigned int, unsigned long, MPI *, MPI **), int (**)( int, MPI * ), - int (**)( int, MPI *, MPI , MPI * ), - int (**)( int, MPI *, MPI *, MPI * ), + int (**)( int, MPI *, MPI , MPI *, int flags ), + int (**)( int, MPI *, MPI *, MPI *, int flags ), int (**)( int, MPI *, MPI , MPI * ), int (**)( int, MPI , MPI *, MPI *, int (*)(void*,MPI), void *), diff --git a/crypto/cipher/dynload.h b/crypto/cipher/dynload.h index 9258352d..0636948d 100644 --- a/crypto/cipher/dynload.h +++ b/crypto/cipher/dynload.h @@ -49,8 +49,8 @@ _gcry_enum_gnupgext_pubkeys( void **enum_context, int *algo, int (**generate)( int algo, unsigned int nbits, unsigned long use_e, MPI *skey, MPI **retfactors ), int (**check_secret_key)( int algo, MPI *skey ), - int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey ), - int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey ), + int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey, int flags ), + int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey, int flags ), int (**sign)( int algo, MPI *resarr, MPI data, MPI *skey ), int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey, int (*cmp)(void *, MPI), void *opaquev ), diff --git a/crypto/cipher/elgamal.c b/crypto/cipher/elgamal.c index ea3a8dd6..a4b54254 100644 --- a/crypto/cipher/elgamal.c +++ b/crypto/cipher/elgamal.c @@ -538,7 +538,7 @@ _gcry_elg_check_secret_key( int algo, MPI *skey ) int -_gcry_elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) +_gcry_elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey, int flags) { ELG_public_key pk; @@ -557,7 +557,7 @@ _gcry_elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) } int -_gcry_elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) +_gcry_elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey, int flags) { ELG_secret_key sk; diff --git a/crypto/cipher/elgamal.h b/crypto/cipher/elgamal.h index ae9f296a..80180646 100644 --- a/crypto/cipher/elgamal.h +++ b/crypto/cipher/elgamal.h @@ -23,8 +23,8 @@ int _gcry_elg_generate( int algo, unsigned int nbits, unsigned long dummy, MPI *skey, MPI **retfactors ); int _gcry_elg_check_secret_key( int algo, MPI *skey ); -int _gcry_elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); -int _gcry_elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); +int _gcry_elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey, int flags); +int _gcry_elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey, int flags ); int _gcry_elg_sign( int algo, MPI *resarr, MPI data, MPI *skey ); int _gcry_elg_verify( int algo, MPI hash, MPI *data, MPI *pkey, int (*cmp)(void *, MPI), void *opaquev ); diff --git a/crypto/cipher/md.c b/crypto/cipher/md.c index e80cb7c5..0cb4f341 100644 --- a/crypto/cipher/md.c +++ b/crypto/cipher/md.c @@ -114,9 +114,6 @@ struct md_digest_list_s { static struct md_digest_list_s *digest_list; -#define digitp(p) (*(p) >= 0 && *(p) <= '9') - - static struct md_digest_list_s * @@ -618,23 +615,27 @@ int gcry_md_ctl( GCRY_MD_HD hd, int cmd, byte *buffer, size_t buflen) { int rc = 0; - if( cmd == GCRYCTL_FINALIZE ) - md_final( hd ); - else if( cmd == GCRYCTL_SET_KEY ) { - rc = gcry_md_setkey ( hd, buffer, buflen ); - } - else if( cmd == GCRYCTL_START_DUMP ) { - md_start_debug( hd, buffer ); - } - else if( cmd == GCRYCTL_STOP_DUMP ) { + + switch (cmd) + { + case GCRYCTL_FINALIZE: + md_final (hd); + break; + case GCRYCTL_SET_KEY: + rc = gcry_md_setkey (hd, buffer, buflen); + break; + case GCRYCTL_START_DUMP: + md_start_debug (hd, buffer); + break; + case GCRYCTL_STOP_DUMP: md_stop_debug( hd ); - } - else + break; + default: rc = GCRYERR_INV_OP; + } return set_lasterr( rc ); } - int gcry_md_setkey( GCRY_MD_HD hd, const void *key, size_t keylen ) { diff --git a/crypto/cipher/md4.c b/crypto/cipher/md4.c index d649f68e..7bb31a8e 100644 --- a/crypto/cipher/md4.c +++ b/crypto/cipher/md4.c @@ -1,5 +1,5 @@ /* md4.c - MD4 Message-Digest Algorithm - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -79,17 +79,6 @@ md4_init( MD4_CONTEXT *ctx ) ctx->count = 0; } -static void -burn_stack (int bytes) -{ - char buf[128]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) @@ -203,7 +192,7 @@ md4_write( MD4_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ transform( hd, hd->buf ); - burn_stack (80+6*sizeof(void*)); + _gcry_burn_stack (80+6*sizeof(void*)); hd->count = 0; hd->nblocks++; } @@ -216,7 +205,7 @@ md4_write( MD4_CONTEXT *hd, byte *inbuf, size_t inlen) if( !inlen ) return; } - burn_stack (80+6*sizeof(void*)); + _gcry_burn_stack (80+6*sizeof(void*)); while( inlen >= 64 ) { transform( hd, inbuf ); @@ -282,7 +271,7 @@ md4_final( MD4_CONTEXT *hd ) hd->buf[62] = msb >> 16; hd->buf[63] = msb >> 24; transform( hd, hd->buf ); - burn_stack (80+6*sizeof(void*)); + _gcry_burn_stack (80+6*sizeof(void*)); p = hd->buf; #ifdef BIG_ENDIAN_HOST diff --git a/crypto/cipher/md5.c b/crypto/cipher/md5.c index f03a301d..9d2f7c88 100644 --- a/crypto/cipher/md5.c +++ b/crypto/cipher/md5.c @@ -1,5 +1,5 @@ /* md5.c - MD5 Message-Digest Algorithm - * Copyright (C) 1995,1996,1998,1999,2001,2002 Free Software Foundation, Inc. + * Copyright (C) 1995,1996,1998,1999,2001,2002,2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -62,18 +62,6 @@ md5_init( MD5_CONTEXT *ctx ) ctx->count = 0; } -static void -burn_stack (int bytes) -{ - char buf[128]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - /* These are the four functions used in the four steps of the MD5 algorithm and defined in the RFC 1321. The first function is a little bit optimized @@ -229,7 +217,7 @@ md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ transform( hd, hd->buf ); - burn_stack (80+6*sizeof(void*)); + _gcry_burn_stack (80+6*sizeof(void*)); hd->count = 0; hd->nblocks++; } @@ -242,7 +230,7 @@ md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen) if( !inlen ) return; } - burn_stack (80+6*sizeof(void*)); + _gcry_burn_stack (80+6*sizeof(void*)); while( inlen >= 64 ) { transform( hd, inbuf ); @@ -308,7 +296,7 @@ md5_final( MD5_CONTEXT *hd ) hd->buf[62] = msb >> 16; hd->buf[63] = msb >> 24; transform( hd, hd->buf ); - burn_stack (80+6*sizeof(void*)); + _gcry_burn_stack (80+6*sizeof(void*)); p = hd->buf; #ifdef BIG_ENDIAN_HOST diff --git a/crypto/cipher/primegen.c b/crypto/cipher/primegen.c index 73f678d4..f2ece0e4 100644 --- a/crypto/cipher/primegen.c +++ b/crypto/cipher/primegen.c @@ -1,5 +1,5 @@ /* primegen.c - prime number generator - * Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -32,8 +32,8 @@ #include "mpi.h" #include "cipher.h" -static int no_of_small_prime_numbers; -static MPI gen_prime( unsigned nbits, int mode, int randomlevel ); +static MPI gen_prime (unsigned int nbits, int secret, int randomlevel, + int (*extra_check)(void *, MPI), void *extra_check_arg); static int check_prime( MPI prime, MPI val_2 ); static int is_prime( MPI n, int steps, int *count ); static void m_out_of_n( char *array, int m, int n ); @@ -125,7 +125,7 @@ static ushort small_prime_numbers[] = { 4957, 4967, 4969, 4973, 4987, 4993, 4999, 0 }; - +static int no_of_small_prime_numbers = DIM (small_prime_numbers) - 1; void _gcry_register_primegen_progress ( void (*cb)(void *,const char*,int,int,int), void *cb_data ) @@ -147,21 +147,25 @@ progress( int c ) * Generate a prime number (stored in secure memory) */ MPI -_gcry_generate_secret_prime( unsigned nbits ) +_gcry_generate_secret_prime (unsigned int nbits, + int (*extra_check)(void*, MPI), + void *extra_check_arg) { MPI prime; - prime = gen_prime( nbits, 1, 2 ); + prime = gen_prime( nbits, 1, 2, extra_check, extra_check_arg); progress('\n'); return prime; } MPI -_gcry_generate_public_prime( unsigned nbits ) +_gcry_generate_public_prime( unsigned int nbits, + int (*extra_check)(void*, MPI), + void *extra_check_arg) { MPI prime; - prime = gen_prime( nbits, 0, 2 ); + prime = gen_prime( nbits, 0, 2, extra_check, extra_check_arg ); progress('\n'); return prime; } @@ -214,8 +218,8 @@ _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits, log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", pbits, req_qbits, qbits, fbits, n ); prime = gcry_mpi_new ( pbits ); - q = gen_prime( qbits, 0, 0 ); - q_factor = mode==1? gen_prime( req_qbits, 0, 0 ) : NULL; + q = gen_prime( qbits, 0, 0, NULL, NULL ); + q_factor = mode==1? gen_prime( req_qbits, 0, 0, NULL, NULL ) : NULL; /* allocate an array to hold the factors + 2 for later usage */ factors = gcry_xcalloc( n+2, sizeof *factors ); @@ -242,7 +246,7 @@ _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits, perms = gcry_xcalloc( 1, m ); for(i=0; i < n; i++ ) { perms[i] = 1; - pool[i] = gen_prime( fbits, 0, 1 ); + pool[i] = gen_prime( fbits, 0, 1, NULL, NULL ); factors[i] = pool[i]; } } @@ -251,7 +255,7 @@ _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits, for(i=j=0; i < m && j < n ; i++ ) if( perms[i] ) { if( !pool[i] ) - pool[i] = gen_prime( fbits, 0, 1 ); + pool[i] = gen_prime( fbits, 0, 1, NULL, NULL ); factors[j++] = pool[i]; } if( i == n ) { @@ -275,7 +279,7 @@ _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits, qbits++; progress('>'); mpi_free (q); - q = gen_prime( qbits, 0, 0 ); + q = gen_prime( qbits, 0, 0, NULL, NULL ); goto next_try; } } @@ -287,7 +291,7 @@ _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits, qbits--; progress('<'); mpi_free (q); - q = gen_prime( qbits, 0, 0 ); + q = gen_prime( qbits, 0, 0, NULL, NULL ); goto next_try; } } @@ -379,92 +383,103 @@ _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits, static MPI -gen_prime( unsigned nbits, int secret, int randomlevel ) +gen_prime (unsigned int nbits, int secret, int randomlevel, + int (*extra_check)(void *, MPI), void *extra_check_arg) { - MPI prime, ptest, pminus1, val_2, val_3, result; - int i; - unsigned x, step; - unsigned count1, count2; - int *mods; - - if( 0 && DBG_CIPHER ) - log_debug("generate a prime of %u bits ", nbits ); - - if( !no_of_small_prime_numbers ) { - for(i=0; small_prime_numbers[i]; i++ ) - no_of_small_prime_numbers++; - } - mods = gcry_xmalloc( no_of_small_prime_numbers * sizeof *mods ); - /* make nbits fit into MPI implementation */ - val_2 = mpi_alloc_set_ui( 2 ); - val_3 = mpi_alloc_set_ui( 3); - prime = secret? gcry_mpi_snew ( nbits ): gcry_mpi_new ( nbits ); - result = mpi_alloc_like( prime ); - pminus1= mpi_alloc_like( prime ); - ptest = mpi_alloc_like( prime ); - count1 = count2 = 0; - for(;;) { /* try forvever */ - int dotcount=0; - - /* generate a random number */ - gcry_mpi_randomize( prime, nbits, randomlevel ); - - /* Set high order bit to 1, set low order bit to 0. If we are - generating a secret prime we are most probably doing that - for RSA, to make sure that the modulus does have the - requested keysize we set the 2 high order bits */ - mpi_set_highbit (prime, nbits-1); - if (secret) - mpi_set_bit (prime, nbits-2); - mpi_set_bit(prime, 0); - - /* calculate all remainders */ - for(i=0; (x = small_prime_numbers[i]); i++ ) - mods[i] = mpi_fdiv_r_ui(NULL, prime, x); - - /* now try some primes starting with prime */ - for(step=0; step < 20000; step += 2 ) { - /* check against all the small primes we have in mods */ - count1++; - for(i=0; (x = small_prime_numbers[i]); i++ ) { - while( mods[i] + step >= x ) - mods[i] -= x; - if( !(mods[i] + step) ) - break; + MPI prime, ptest, pminus1, val_2, val_3, result; + int i; + unsigned x, step; + unsigned count1, count2; + int *mods; + + if( 0 && DBG_CIPHER ) + log_debug("generate a prime of %u bits ", nbits ); + + mods = gcry_xmalloc( no_of_small_prime_numbers * sizeof *mods ); + /* make nbits fit into MPI implementation */ + val_2 = mpi_alloc_set_ui( 2 ); + val_3 = mpi_alloc_set_ui( 3); + prime = secret? gcry_mpi_snew ( nbits ): gcry_mpi_new ( nbits ); + result = mpi_alloc_like( prime ); + pminus1= mpi_alloc_like( prime ); + ptest = mpi_alloc_like( prime ); + count1 = count2 = 0; + for (;;) + { /* try forvever */ + int dotcount=0; + + /* generate a random number */ + gcry_mpi_randomize( prime, nbits, randomlevel ); + + /* Set high order bit to 1, set low order bit to 0. If we are + generating a secret prime we are most probably doing that + for RSA, to make sure that the modulus does have the + requested keysize we set the 2 high order bits */ + mpi_set_highbit (prime, nbits-1); + if (secret) + mpi_set_bit (prime, nbits-2); + mpi_set_bit(prime, 0); + + /* calculate all remainders */ + for (i=0; (x = small_prime_numbers[i]); i++ ) + mods[i] = mpi_fdiv_r_ui(NULL, prime, x); + + /* now try some primes starting with prime */ + for(step=0; step < 20000; step += 2 ) + { + /* check against all the small primes we have in mods */ + count1++; + for (i=0; (x = small_prime_numbers[i]); i++ ) + { + while ( mods[i] + step >= x ) + mods[i] -= x; + if ( !(mods[i] + step) ) + break; } - if( x ) - continue; /* found a multiple of an already known prime */ - - mpi_add_ui( ptest, prime, step ); - - /* do a faster Fermat test */ - count2++; - mpi_sub_ui( pminus1, ptest, 1); - gcry_mpi_powm( result, val_2, pminus1, ptest ); - if( !mpi_cmp_ui( result, 1 ) ) { /* not composite */ - /* perform stronger tests */ - if( is_prime(ptest, 5, &count2 ) ) { - if( !mpi_test_bit( ptest, nbits-1-secret ) ) { + if ( x ) + continue; /* found a multiple of an already known prime */ + + mpi_add_ui( ptest, prime, step ); + + /* do a faster Fermat test */ + count2++; + mpi_sub_ui( pminus1, ptest, 1); + gcry_mpi_powm( result, val_2, pminus1, ptest ); + if ( !mpi_cmp_ui( result, 1 ) ) + { /* not composite, perform stronger tests */ + if (is_prime(ptest, 5, &count2 )) + { + if (!mpi_test_bit( ptest, nbits-1-secret )) + { progress('\n'); log_debug("overflow in prime generation\n"); - break; /* step loop, continue with a new prime */ - } - - mpi_free(val_2); - mpi_free(val_3); - mpi_free(result); - mpi_free(pminus1); - mpi_free(prime); - gcry_free(mods); - return ptest; - } + break; /* stop loop, continue with a new prime */ + } + + if (extra_check && extra_check (ptest, extra_check_arg)) + { /* The extra check told us that this prime is + not of the caller's taste. */ + progress ('/'); + } + else + { /* got it */ + mpi_free(val_2); + mpi_free(val_3); + mpi_free(result); + mpi_free(pminus1); + mpi_free(prime); + gcry_free(mods); + return ptest; + } + } } - if( ++dotcount == 10 ) { - progress('.'); - dotcount = 0; + if (++dotcount == 10 ) + { + progress('.'); + dotcount = 0; } } - progress(':'); /* restart with a new random value */ + progress(':'); /* restart with a new random value */ } } diff --git a/crypto/cipher/pubkey.c b/crypto/cipher/pubkey.c index d0a493de..a0497d63 100644 --- a/crypto/cipher/pubkey.c +++ b/crypto/cipher/pubkey.c @@ -37,6 +37,8 @@ #define TABLE_SIZE 10 + + struct pubkey_table_s { const char *name; int algo; @@ -48,8 +50,8 @@ struct pubkey_table_s { int (*generate)(int algo, unsigned int nbits, unsigned long use_e, MPI *skey, MPI **retfactors ); int (*check_secret_key)( int algo, MPI *skey ); - int (*encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey ); - int (*decrypt)( int algo, MPI *result, MPI *data, MPI *skey ); + int (*encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey, int flags); + int (*decrypt)( int algo, MPI *result, MPI *data, MPI *skey, int flags); int (*sign)( int algo, MPI *resarr, MPI data, MPI *skey ); int (*verify)( int algo, MPI hash, MPI *data, MPI *pkey, int (*cmp)(void *, MPI), void *opaquev ); @@ -106,7 +108,7 @@ static struct { }; -static int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); +static int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey, int flags); static int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey ); static int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey, int (*cmp)(void *, MPI), void *opaque ); @@ -121,11 +123,11 @@ dummy_check_secret_key( int algo, MPI *skey ) { log_bug("no check_secret_key() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; } static int -dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) +dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey, int flags) { log_bug("no encrypt() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; } static int -dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) +dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey, int flags) { log_bug("no decrypt() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; } static int @@ -526,7 +528,8 @@ pubkey_check_secret_key( int algo, MPI *skey ) * algorithm allows this - check with pubkey_get_nenc() ) */ static int -pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) +pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey, + int flags ) { int i, rc; @@ -540,7 +543,7 @@ pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) { - rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey ); + rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey, flags); goto ready; } } while( load_pubkey_modules() ); @@ -563,7 +566,8 @@ pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) * newly allocated mpi or NULL in case of an error. */ static int -pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) +pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey, + int flags) { int i, rc; @@ -579,7 +583,7 @@ pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) { - rc = (*pubkey_table[i].decrypt)( algo, result, data, skey ); + rc = (*pubkey_table[i].decrypt)( algo, result, data, skey, flags ); goto ready; } } while( load_pubkey_modules() ); @@ -867,7 +871,8 @@ sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo) */ static int sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo, - int *ret_modern, int *ret_want_pkcs1) + int *ret_modern, int *ret_want_pkcs1, + int *flags) { GCRY_SEXP list, l2; const char *name; @@ -875,6 +880,7 @@ sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo, size_t n; int i, idx; int algo; + int parsed_flags = 0; const char *elems; GCRY_MPI *array; @@ -909,6 +915,8 @@ sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo, ; /* just a dummy because it is the default */ else if ( n == 5 && !memcmp (s, "pkcs1", 5)) *ret_want_pkcs1 = 1; + else if ( n == 11 && !memcmp (s, "no-blinding", 11)) + parsed_flags |= PUBKEY_FLAG_NO_BLINDING; else { gcry_sexp_release (l2); @@ -972,6 +980,8 @@ sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo, *retarray = array; *retalgo = algo; + *flags = parsed_flags; + return 0; } @@ -997,7 +1007,7 @@ sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo, */ static int sexp_data_to_mpi (GcrySexp input, unsigned int nbits, GcryMPI *ret_mpi, - int for_encryption) + int for_encryption, int *flags) { int rc = 0; GcrySexp ldata, lhash, lvalue; @@ -1005,7 +1015,11 @@ sexp_data_to_mpi (GcrySexp input, unsigned int nbits, GcryMPI *ret_mpi, size_t n; const char *s; int is_raw = 0, is_pkcs1 = 0, unknown_flag=0; + int parsed_flags = 0, dummy_flags; + if (! flags) + flags = &dummy_flags; + *ret_mpi = NULL; ldata = gcry_sexp_find_token (input, "data", 0); if (!ldata) @@ -1028,6 +1042,8 @@ sexp_data_to_mpi (GcrySexp input, unsigned int nbits, GcryMPI *ret_mpi, is_raw = 1; else if ( n == 5 && !memcmp (s, "pkcs1", 5)) is_pkcs1 = 1; + else if (n == 11 && ! memcmp (s, "no-blinding", 11)) + parsed_flags |= PUBKEY_FLAG_NO_BLINDING; else unknown_flag = 1; } @@ -1206,6 +1222,10 @@ sexp_data_to_mpi (GcrySexp input, unsigned int nbits, GcryMPI *ret_mpi, gcry_sexp_release (ldata); gcry_sexp_release (lhash); gcry_sexp_release (lvalue); + + if (! rc) + *flags = parsed_flags; + return rc; } @@ -1237,8 +1257,8 @@ gcry_pk_encrypt (GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey) { MPI *pkey, data, *ciph; const char *key_algo_name, *algo_name, *algo_elems; - int i, rc, algo; - + int i, rc, algo, flags; + *r_ciph = NULL; /* get the key */ rc = sexp_to_key( s_pkey, 0, &pkey, &algo, &i); @@ -1267,7 +1287,8 @@ gcry_pk_encrypt (GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey) algo_elems = enc_info_table[i].elements; /* get the stuff we want to encrypt */ - rc = sexp_data_to_mpi (s_data, gcry_pk_get_nbits (s_pkey), &data, 1); + rc = sexp_data_to_mpi (s_data, gcry_pk_get_nbits (s_pkey), &data, 1, + &flags); if (rc) { release_mpi_array( pkey ); gcry_free (pkey); @@ -1276,7 +1297,7 @@ gcry_pk_encrypt (GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey) /* Now we can encrypt data to ciph */ ciph = gcry_xcalloc( (strlen(algo_elems)+1) , sizeof *ciph ); - rc = pubkey_encrypt( algo, ciph, data, pkey ); + rc = pubkey_encrypt( algo, ciph, data, pkey, flags ); release_mpi_array( pkey ); gcry_free (pkey); pkey = NULL; mpi_free( data ); @@ -1289,14 +1310,20 @@ gcry_pk_encrypt (GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey) /* We did it. Now build the return list */ { char *string, *p; - size_t nelem, needed= strlen(algo_name) + 20; + size_t nelem, needed= strlen(algo_name) + 30; + + /* FIXME, this calculation needs to be cleaned up. + -moritz */ /* count elements, so that we can allocate enough space */ for(nelem=0; algo_elems[nelem]; nelem++ ) needed += 10; /* 6 + a safety margin */ /* build the string */ string = p = gcry_xmalloc ( needed ); - p = stpcpy ( p, "(enc-val(" ); + p = stpcpy ( p, "(enc-val(flags " ); + if (flags & PUBKEY_FLAG_NO_BLINDING) + p = stpcpy (p, "no-blinding"); + p = stpcpy (p, ")("); p = stpcpy ( p, algo_name ); for(i=0; algo_elems[i]; i++ ) { *p++ = '('; @@ -1366,14 +1393,15 @@ int gcry_pk_decrypt( GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey ) { MPI *skey, *data, plain; - int rc, algo, dataalgo, modern, want_pkcs1; - + int rc, algo, dataalgo, modern, want_pkcs1, flags; + *r_plain = NULL; rc = sexp_to_key( s_skey, 1, &skey, &algo, NULL ); if( rc ) { return rc; } - rc = sexp_to_enc( s_data, &data, &dataalgo, &modern, &want_pkcs1 ); + rc = sexp_to_enc( s_data, &data, &dataalgo, &modern, &want_pkcs1, + &flags ); if( rc ) { release_mpi_array( skey ); gcry_free (skey); @@ -1387,7 +1415,7 @@ gcry_pk_decrypt( GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey ) return GCRYERR_CONFLICT; /* key algo does not match data algo */ } - rc = pubkey_decrypt( algo, &plain, data, skey ); + rc = pubkey_decrypt( algo, &plain, data, skey, flags ); if( rc ) { release_mpi_array( skey ); gcry_free (skey); @@ -1473,7 +1501,7 @@ gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey ) /* get the stuff we want to sign */ /* Note that pk_get_nbits does also work on a private key */ - rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_skey), &hash, 0); + rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_skey), &hash, 0, NULL); if (rc) { release_mpi_array( skey ); gcry_free (skey); @@ -1571,7 +1599,7 @@ gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey ) return GCRYERR_CONFLICT; /* algo does not match */ } - rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_pkey), &hash, 0); + rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_pkey), &hash, 0, 0); if (rc) { release_mpi_array( pkey ); gcry_free (pkey); diff --git a/crypto/cipher/random.c b/crypto/cipher/random.c index f7b23787..60445fba 100644 --- a/crypto/cipher/random.c +++ b/crypto/cipher/random.c @@ -188,19 +188,6 @@ _gcry_random_initialize () initialize (); } - -static void -burn_stack (int bytes) -{ - char buf[128]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - void _gcry_random_dump_stats() { @@ -461,7 +448,7 @@ mix_pool(byte *pool) _gcry_rmd160_hash_buffer (failsafe_digest, pool, POOLSIZE); failsafe_digest_valid = 1; } - burn_stack (384); /* for the rmd160_mixblock(), rmd160_hash_buffer */ + _gcry_burn_stack (384); /* for the rmd160_mixblock(), rmd160_hash_buffer */ } void diff --git a/crypto/cipher/rijndael.c b/crypto/cipher/rijndael.c index f4b1fdd9..b7c7d18b 100644 --- a/crypto/cipher/rijndael.c +++ b/crypto/cipher/rijndael.c @@ -1,5 +1,5 @@ /* Rijndael (AES) for GnuPG - * Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -1707,17 +1707,6 @@ static const u32 rcon[30] = { -static void -burn_stack (int bytes) -{ - char buf[64]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - /* Perform the key setup. */ @@ -1825,7 +1814,7 @@ static int rijndael_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) { int rc = do_setkey (ctx, key, keylen); - burn_stack ( 100 + 16*sizeof(int)); + _gcry_burn_stack ( 100 + 16*sizeof(int)); return rc; } @@ -1950,7 +1939,7 @@ static void rijndael_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a) { do_encrypt (ctx, b, a); - burn_stack (16 + 2*sizeof(int)); + _gcry_burn_stack (16 + 2*sizeof(int)); } @@ -1966,7 +1955,7 @@ do_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a) if ( !ctx->decryption_prepared ) { prepare_decryption ( ctx ); - burn_stack (64); + _gcry_burn_stack (64); ctx->decryption_prepared = 1; } @@ -2045,7 +2034,7 @@ static void rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a) { do_decrypt (ctx, b, a); - burn_stack (16+2*sizeof(int)); + _gcry_burn_stack (16+2*sizeof(int)); } /* Test a single encryption and decryption with each key size. */ diff --git a/crypto/cipher/rmd160.c b/crypto/cipher/rmd160.c index 3680f0ad..4cf52c51 100644 --- a/crypto/cipher/rmd160.c +++ b/crypto/cipher/rmd160.c @@ -1,5 +1,5 @@ /* rmd160.c - RIPE-MD160 - * Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -141,18 +141,6 @@ * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 */ -static void -burn_stack (int bytes) -{ - char buf[150]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - void _gcry_rmd160_init( RMD160_CONTEXT *hd ) @@ -414,7 +402,7 @@ rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ transform( hd, hd->buf ); - burn_stack (108+5*sizeof(void*)); + _gcry_burn_stack (108+5*sizeof(void*)); hd->count = 0; hd->nblocks++; } @@ -435,7 +423,7 @@ rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) inlen -= 64; inbuf += 64; } - burn_stack (108+5*sizeof(void*)); + _gcry_burn_stack (108+5*sizeof(void*)); for( ; inlen && hd->count < 64; inlen-- ) hd->buf[hd->count++] = *inbuf++; } @@ -508,7 +496,7 @@ rmd160_final( RMD160_CONTEXT *hd ) hd->buf[62] = msb >> 16; hd->buf[63] = msb >> 24; transform( hd, hd->buf ); - burn_stack (108+5*sizeof(void*)); + _gcry_burn_stack (108+5*sizeof(void*)); p = hd->buf; #ifdef BIG_ENDIAN_HOST diff --git a/crypto/cipher/rsa.c b/crypto/cipher/rsa.c index a8097be2..57aedaf1 100644 --- a/crypto/cipher/rsa.c +++ b/crypto/cipher/rsa.c @@ -83,6 +83,24 @@ test_keys( RSA_secret_key *sk, unsigned nbits ) gcry_mpi_release ( out2 ); } + +/* Callback used by the prime generation to test whether the exponent + is suitable. Returns 0 if the test has been passed. */ +static int +check_exponent (void *arg, MPI a) +{ + MPI e = arg; + MPI tmp; + int result; + + mpi_sub_ui (a, a, 1); + tmp = _gcry_mpi_alloc_like (a); + result = !gcry_mpi_gcd(tmp, e, a); /* GCD is not 1. */ + gcry_mpi_release (tmp); + mpi_add_ui (a, a, 1); + return result; +} + /**************** * Generate a key pair with a key of size NBITS. * USE_E = 0 let Libcgrypt decide what exponent to use. @@ -108,6 +126,27 @@ generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e) if ( (nbits&1) ) nbits++; + if (use_e == 1) /* Alias for a secure value. */ + use_e = 65537; /* as demanded by Spinx. */ + + /* Public exponent: + In general we use 41 as this is quite fast and more secure than the + commonly used 17. Benchmarking the RSA verify function + with a 1024 bit key yields (2001-11-08): + e=17 0.54 ms + e=41 0.75 ms + e=257 0.95 ms + e=65537 1.80 ms + */ + e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); + if (!use_e) + mpi_set_ui (e, 41); /* This is a reasonable secure and fast value */ + else + { + use_e |= 1; /* make sure this is odd */ + mpi_set_ui (e, use_e); + } + n = gcry_mpi_new (nbits); p = q = NULL; @@ -117,8 +156,17 @@ generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e) gcry_mpi_release (p); if (q) gcry_mpi_release (q); - p = _gcry_generate_secret_prime (nbits/2); - q = _gcry_generate_secret_prime (nbits/2); + if (use_e) + { /* Do an extra test to ensure that the given exponent is + suitable. */ + p = _gcry_generate_secret_prime (nbits/2, check_exponent, e); + q = _gcry_generate_secret_prime (nbits/2, check_exponent, e); + } + else + { /* We check the exponent later. */ + p = _gcry_generate_secret_prime (nbits/2, NULL, NULL); + q = _gcry_generate_secret_prime (nbits/2, NULL, NULL); + } if (mpi_cmp (p, q) > 0 ) /* p shall be smaller than q (for calc of u)*/ mpi_swap(p,q); /* calculate the modulus */ @@ -137,25 +185,13 @@ generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e) gcry_mpi_gcd(g, t1, t2); mpi_fdiv_q(f, phi, g); - /* find an public exponent. - We use 41 as this is quite fast and more secure than the - commonly used 17. Benchmarking the RSA verify function - with a 1024 bit key yields (2001-11-08): - e=17 0.54 ms - e=41 0.75 ms - e=257 0.95 ms - e=65537 1.80 ms - */ - e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - if (!use_e) - use_e = 41; /* This is a reasonable secure and fast value */ - else if (use_e == 1) - use_e = 65537; /* A secure value as demanded by Spinx. */ - - use_e |= 1; /* make sure this is odd */ - mpi_set_ui (e, use_e); while (!gcry_mpi_gcd(t1, e, phi)) /* (while gcd is not 1) */ - mpi_add_ui (e, e, 2); + { + if (use_e) + BUG (); /* The prime generator already made sure that we + never can get to here. */ + mpi_add_ui (e, e, 2); + } /* calculate the secret key d = e^1 mod phi */ d = gcry_mpi_snew ( nbits ); @@ -396,7 +432,8 @@ _gcry_rsa_check_secret_key( int algo, MPI *skey ) int -_gcry_rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) +_gcry_rsa_encrypt (int algo, MPI *resarr, MPI data, MPI *pkey, + int flags) { RSA_public_key pk; @@ -410,22 +447,123 @@ _gcry_rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) return 0; } +/* Perform RSA blinding. */ +GcryMPI +_gcry_rsa_blind (MPI x, MPI r, MPI e, MPI n) +{ + /* A helper. */ + GcryMPI a; + + /* Result. */ + GcryMPI y; + + a = gcry_mpi_snew (gcry_mpi_get_nbits (n)); + y = gcry_mpi_snew (gcry_mpi_get_nbits (n)); + + /* Now we calculate: y = (x * r^e) mod n, where r is the random + number, e is the public exponent, x is the non-blinded data and n + is the RSA modulus. */ + gcry_mpi_powm (a, r, e, n); + gcry_mpi_mulm (y, a, x, n); + + gcry_mpi_release (a); + + return y; +} + +/* Undo RSA blinding. */ +GcryMPI +_gcry_rsa_unblind (MPI x, MPI ri, MPI n) +{ + GcryMPI y; + + y = gcry_mpi_snew (gcry_mpi_get_nbits (n)); + + /* Here we calculate: y = (x * r^-1) mod n, where x is the blinded + decrypted data, ri is the modular multiplicative inverse of r and + n is the RSA modulus. */ + + gcry_mpi_mulm (y, ri, x, n); + + return y; +} + int -_gcry_rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) +_gcry_rsa_decrypt (int algo, MPI *result, MPI *data, MPI *skey, + int flags) { RSA_secret_key sk; - - if( algo != 1 && algo != 2 ) + GcryMPI r = MPI_NULL; /* Random number needed for + blinding. */ + GcryMPI ri = MPI_NULL; /* Modular multiplicative inverse of + r. */ + GcryMPI x = MPI_NULL; /* Data to decrypt. */ + GcryMPI y; /* Result. */ + + if (algo != 1 && algo != 2) return GCRYERR_INV_PK_ALGO; + /* Extract private key. */ sk.n = skey[0]; sk.e = skey[1]; sk.d = skey[2]; sk.p = skey[3]; sk.q = skey[4]; sk.u = skey[5]; - *result = mpi_alloc_secure( mpi_get_nlimbs( sk.n ) ); - secret( *result, data[0], &sk ); + + y = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); + + if (! (flags & PUBKEY_FLAG_NO_BLINDING)) + { + /* Initialize blinding. */ + + /* First, we need a random number r between 0 and n - 1, which + is relatively prime to n (i.e. it is neither p nor q). */ + r = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); + ri = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); + + gcry_mpi_randomize (r, gcry_mpi_get_nbits (sk.n), + GCRY_STRONG_RANDOM); + gcry_mpi_mod (r, r, sk.n); + + /* Actually it should be okay to skip the check for equality + with either p or q here. */ + + /* Calculate inverse of r. */ + if (! gcry_mpi_invm (ri, r, sk.n)) + BUG (); + } + + if (! (flags & PUBKEY_FLAG_NO_BLINDING)) + /* Do blinding. */ + x = _gcry_rsa_blind (data[0], r, sk.e, sk.n); + else + /* Skip blinding. */ + x = data[0]; + + /* Do the encryption. */ + secret (y, x, &sk); + + if (! (flags & PUBKEY_FLAG_NO_BLINDING)) + { + /* Undo blinding. */ + GcryMPI a = gcry_mpi_copy (y); + + gcry_mpi_release (y); + y = _gcry_rsa_unblind (a, ri, sk.n); + } + + if (! (flags & PUBKEY_FLAG_NO_BLINDING)) + { + /* Deallocate resources needed for blinding. */ + gcry_mpi_release (x); + gcry_mpi_release (r); + gcry_mpi_release (ri); + } + + /* Copy out result. */ + *result = y; + return 0; } diff --git a/crypto/cipher/rsa.h b/crypto/cipher/rsa.h index 8bd77f66..58be7a3f 100644 --- a/crypto/cipher/rsa.h +++ b/crypto/cipher/rsa.h @@ -24,8 +24,8 @@ int _gcry_rsa_generate( int algo, unsigned int nbits, unsigned long use_e, MPI *skey, MPI **retfactors ); int _gcry_rsa_check_secret_key( int algo, MPI *skey ); -int _gcry_rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); -int _gcry_rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); +int _gcry_rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey, int flags); +int _gcry_rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey, int flags); int _gcry_rsa_sign( int algo, MPI *resarr, MPI data, MPI *skey ); int _gcry_rsa_verify( int algo, MPI hash, MPI *data, MPI *pkey, int (*cmp)(void *, MPI), void *opaquev ); diff --git a/crypto/cipher/sha1.c b/crypto/cipher/sha1.c index b1caf218..a6339b38 100644 --- a/crypto/cipher/sha1.c +++ b/crypto/cipher/sha1.c @@ -1,5 +1,5 @@ /* sha1.c - SHA1 hash function - * Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -49,18 +49,6 @@ typedef struct { static void -burn_stack (int bytes) -{ - char buf[128]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - -static void sha1_init( SHA1_CONTEXT *hd ) { hd->h0 = 0x67452301; @@ -222,7 +210,7 @@ sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ transform( hd, hd->buf ); - burn_stack (88+4*sizeof(void*)); + _gcry_burn_stack (88+4*sizeof(void*)); hd->count = 0; hd->nblocks++; } @@ -243,7 +231,7 @@ sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen) inlen -= 64; inbuf += 64; } - burn_stack (88+4*sizeof(void*)); + _gcry_burn_stack (88+4*sizeof(void*)); for( ; inlen && hd->count < 64; inlen-- ) hd->buf[hd->count++] = *inbuf++; } @@ -300,7 +288,7 @@ sha1_final(SHA1_CONTEXT *hd) hd->buf[62] = lsb >> 8; hd->buf[63] = lsb ; transform( hd, hd->buf ); - burn_stack (88+4*sizeof(void*)); + _gcry_burn_stack (88+4*sizeof(void*)); p = hd->buf; #ifdef BIG_ENDIAN_HOST diff --git a/crypto/cipher/sha256.c b/crypto/cipher/sha256.c index 9eb2bbe2..1aafd334 100644 --- a/crypto/cipher/sha256.c +++ b/crypto/cipher/sha256.c @@ -53,18 +53,6 @@ typedef struct { static void -burn_stack (int bytes) -{ - char buf[128]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - -static void sha256_init (SHA256_CONTEXT *hd) { hd->h0 = 0x6a09e667; @@ -190,7 +178,7 @@ sha256_write (SHA256_CONTEXT *hd, byte *inbuf, size_t inlen) if (hd->count == 64) { /* flush the buffer */ transform (hd, hd->buf); - burn_stack (74*4+32); + _gcry_burn_stack (74*4+32); hd->count = 0; hd->nblocks++; } @@ -213,7 +201,7 @@ sha256_write (SHA256_CONTEXT *hd, byte *inbuf, size_t inlen) inlen -= 64; inbuf += 64; } - burn_stack (74*4+32); + _gcry_burn_stack (74*4+32); for (; inlen && hd->count < 64; inlen--) hd->buf[hd->count++] = *inbuf++; } @@ -270,7 +258,7 @@ sha256_final(SHA256_CONTEXT *hd) hd->buf[62] = lsb >> 8; hd->buf[63] = lsb; transform (hd, hd->buf); - burn_stack (74*4+32); + _gcry_burn_stack (74*4+32); p = hd->buf; #ifdef BIG_ENDIAN_HOST diff --git a/crypto/cipher/tiger.c b/crypto/cipher/tiger.c index 7ee60bd7..432948b8 100644 --- a/crypto/cipher/tiger.c +++ b/crypto/cipher/tiger.c @@ -1,5 +1,5 @@ /* tiger.c - The TIGER hash function - * Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -589,18 +589,6 @@ static u64 sbox4[256] = { }; -static void -burn_stack (int bytes) -{ - char buf[256]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - static void tiger_init( TIGER_CONTEXT *hd ) @@ -734,7 +722,7 @@ tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ transform( hd, hd->buf ); - burn_stack (21*8+11*sizeof(void*)); + _gcry_burn_stack (21*8+11*sizeof(void*)); hd->count = 0; hd->nblocks++; } @@ -755,7 +743,7 @@ tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen) inlen -= 64; inbuf += 64; } - burn_stack (21*8+11*sizeof(void*)); + _gcry_burn_stack (21*8+11*sizeof(void*)); for( ; inlen && hd->count < 64; inlen-- ) hd->buf[hd->count++] = *inbuf++; } @@ -809,7 +797,7 @@ tiger_final( TIGER_CONTEXT *hd ) hd->buf[62] = msb >> 16; hd->buf[63] = msb >> 24; transform( hd, hd->buf ); - burn_stack (21*8+11*sizeof(void*)); + _gcry_burn_stack (21*8+11*sizeof(void*)); p = hd->buf; #ifdef BIG_ENDIAN_HOST diff --git a/crypto/cipher/twofish.c b/crypto/cipher/twofish.c index 4898b4ba..8fb5f4b4 100644 --- a/crypto/cipher/twofish.c +++ b/crypto/cipher/twofish.c @@ -1,5 +1,5 @@ /* Twofish for GPG - * Copyright (C) 1998, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc. * Written by Matthew Skala , July 26, 1998 * 256-bit key length added March 20, 1999 * Some modifications to reduce the text size by Werner Koch, April, 1998 @@ -560,17 +560,6 @@ static byte calc_sb_tbl[512] = { ctx->a[(j) + 1] = (y << 9) + (y >> 23) -static void -burn_stack (int bytes) -{ - char buf[64]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - /* Perform the key setup. Note that this works only with 128- and 256-bit * keys, despite the API that looks like it might support other sizes. */ @@ -714,7 +703,7 @@ static int twofish_setkey (TWOFISH_context *ctx, const byte *key, unsigned int keylen) { int rc = do_twofish_setkey (ctx, key, keylen); - burn_stack (23+6*sizeof(void*)); + _gcry_burn_stack (23+6*sizeof(void*)); return rc; } @@ -816,7 +805,7 @@ static void twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) { do_twofish_encrypt (ctx, out, in); - burn_stack (24+3*sizeof (void*)); + _gcry_burn_stack (24+3*sizeof (void*)); } @@ -858,7 +847,7 @@ static void twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) { do_twofish_decrypt (ctx, out, in); - burn_stack (24+3*sizeof (void*)); + _gcry_burn_stack (24+3*sizeof (void*)); } diff --git a/crypto/doc/ChangeLog b/crypto/doc/ChangeLog index 41f58de1..9db2465f 100644 --- a/crypto/doc/ChangeLog +++ b/crypto/doc/ChangeLog @@ -1,3 +1,11 @@ +2003-03-22 Simon Josefsson + + * gcrypt.texi: Add CBC-MAC. + +2003-03-04 Moritz Schulte + + * gcrypt.texi (Cipher Functions): Added gcry_cipher_reset. + 2003-01-23 Werner Koch * gcrypt.texi (gcry_pk_decrypt): Described use of FLAGS diff --git a/crypto/doc/gcrypt.texi b/crypto/doc/gcrypt.texi index 524ea53a..ac247139 100644 --- a/crypto/doc/gcrypt.texi +++ b/crypto/doc/gcrypt.texi @@ -72,7 +72,7 @@ entitled ``GNU Free Documentation License''. @top Main Menu This is Edition @value{EDITION}, last updated @value{UPDATED}, of @cite{The `Libgcrypt' Reference Manual}, for Version -@value{VERSION} of the @acronym{GPGME} library. +@value{VERSION} of the @acronym{Libgcrypt} library. @end ifnottex @menu @@ -396,7 +396,12 @@ This flag enables the CFB sync mode, which is a special feature of Libgcrypt's CFB mode implementation to allow for OpenPGP's CFB variant. See @code{gcry_cipher_sync}. @item GCRY_CIPHER_CBC_CTS -Enable cipher text stealing for the CBS mode. +Enable cipher text stealing (CTS) for the CBC mode. Cannot be used +simultaneous as GCRY_CIPHER_CBC_MAC. +@item GCRY_CIPHER_CBC_MAC +Compute CBC-MAC keyed checksums. This is the same as CBC mode, but +only output the last block. Cannot be used simultaneous as +GCRY_CIPHER_CBC_CTS. @end table @end deftypefun @@ -439,6 +444,13 @@ requirement of the selected algorithm and mode. Note, that this is implemented as a macro. @end deftypefun +@deftypefun int gcry_cipher_reset (GCRY_CIPHER_HD @var{h}) + +Set the given handle's context back to the state it had after the last +call to gcry_cipher_setkey and clear the initialization vector. + +Note, that gcry_cipher_reset is implemented as a macro. +@end deftypefun The actual encryption and decryption is done by using one of the following functions. They may be used as often as required to process @@ -683,6 +695,8 @@ this is the hashed data is highly confidential. @item GCRY_MD_FLAG_HMAC Turn the algorithm into a HMAC message authentication algorithm. Note that the function @code{gcry_md_setkey} must be used set the MAC key. +If you want CBC message authenentication codes based on a cipher, see +@xref{Cipher Functions}. @end table @c begin table of hash flags @@ -2450,5 +2464,56 @@ message to the user. @contents @bye + /* Version check should be the very first gcry call because it + makes sure that constructor functrions are run. */ + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + /* Many applications don't require secure memory, so they should + disable it right away. There won't be a problem unless one makes + use of a feature which requires secure memoery - in that case the + process would abort becuase the secmem is not initialized. */ + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + + /* .. add whatever initialization you want, but better don't make calls + to libgcrypt from more than one thread ... */ + + /* Tell Libgcrypt that initialization has completed. */ + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + + +If you require secure memory, this code should be used: + + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + /* We don't want to see any warnings, e.g. because we have not yet + parsed options which might be used to suppress such warnings */ + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + + /* ... */ + + /* Allocate a pool of 16k secure memory. This also drops priviliges + on some systems. */ + gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + + /* It is now okay to let Libgcrypt complain when there was/is a problem + with the secure memory. */ + gcry_control (GCRYCTL_RESUME_SECMEM_WARN); + + /* Tell Libgcrypt that initialization has completed. */ + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + + +This sounds a bit complicated but has the advantage that the caller +must decide whether he wants secure memory or not - there is no +default. + +It is important that this initialization is not done by a library but +in the application. The library might want to check for finished +initialization using: + + if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) + return MYLIB_ERROR_LIBGCRYPT_NOT_INITIALIZED; + + @c LocalWords: int HD diff --git a/crypto/scripts/ChangeLog b/crypto/scripts/ChangeLog index 7d40558c..5ca6e18d 100644 --- a/crypto/scripts/ChangeLog +++ b/crypto/scripts/ChangeLog @@ -1,3 +1,8 @@ +2003-03-06 Moritz Schulte + + * autogen.sh (run): New function. + Let automake run with -a for adding missing files automatically + 2002-11-12 Werner Koch * config.sub, config.guess: Updated from ftp.gnu.org/gnu/config diff --git a/crypto/scripts/autogen.sh b/crypto/scripts/autogen.sh index c795ee8f..35daf38c 100755 --- a/crypto/scripts/autogen.sh +++ b/crypto/scripts/autogen.sh @@ -1,6 +1,6 @@ #!/bin/sh # Run this to generate all the initial makefiles, etc. -# Copyright (C) 2002 Free Software Foundation, Inc. +# Copyright (C) 2002, 2003 Free Software Foundation, Inc. # # This file is part of Libgcrypt. # @@ -159,14 +159,15 @@ fi echo "Running libtoolize... Ignore non-fatal messages." echo "no" | libtoolize +run() +{ + echo "Running $@..." + $@ +} -echo "Running aclocal..." -aclocal -echo "Running autoheader..." -autoheader -echo "Running automake --gnu ..." -automake --gnu; -echo "Running autoconf..." -autoconf +run aclocal +run autoheader +run automake --gnu -a +run autoconf echo "You can now run \"./configure --enable-maintainer-mode\" and then \"make\"." diff --git a/crypto/src/ChangeLog b/crypto/src/ChangeLog index 93277af7..2144e916 100644 --- a/crypto/src/ChangeLog +++ b/crypto/src/ChangeLog @@ -1,3 +1,62 @@ +2003-03-19 Moritz Schulte + + * cipher.h (PUBKEY_FLAG_NO_BLINDING): New symbol. + +2003-03-22 Simon Josefsson + + * gcrypt.h: Add GCRYCTL_SET_CBC_MAC and GCRY_CIPHER_CBC_MAC. + +2003-03-19 Werner Koch + + * g10lib.h: Adjusted primegen.c prototypes. + +2003-03-12 Werner Koch + + * sexp.c (sexp_sscan): Initialize NM. Thanks to Ian Peters for + valgrinding this. + +2003-03-06 Moritz Schulte + + * secmem.h (GCRY_SECMEM_FLAG_NO_WARNING, + GCRY_SECMEM_FLAG_SUSPEND_WARNING): New symbols. + + * global.c (gcry_control): Use + GCRY_SECMEM_FLAG_{NO,SUSPEND}_WARNING, instead of hard-coded + values. + * secmem.c (_gcry_secmem_set_flags): Likewise. + * secmem.c (_gcry_secmem_get_flags): Likewise. + +2003-03-03 Moritz Schulte + + * misc.c: Removed old FIXME, since there is already a function to + set the value of `verbosity_level'. + + * gcrypt.h: Removed enumeration list: gcry_ctl_cmds. + New enumeration lists: gcry_global_control_cmds, + gcry_control_cmds, gcry_info_cmds, gcry_algo_info_cmds. + +2003-03-02 Moritz Schulte + + * gcrypt.h (gcry_cipher_reset): New macro for resetting a handle. + +2003-02-28 Moritz Schulte + + * secmem.c (DEFAULT_PAGESIZE): New symbol. + (init_pool): Use DEFAULT_PAGESIZE. + +2003-02-23 Moritz Schulte + + * secmem.h: Fix typo in declaration of _gcry_secmem_term. + + * sexp.c: Move macro definitions of `digitp', `octdigit', `alphap' + and `hexdigit' ... + * g10lib.h: ... here. + + * misc.c (_gcry_burn_stack): New function (former name: + burn_stack). + + * g10lib.h (burn_stack): Declare _gcry_burn_stack(). + 2003-01-24 Werner Koch * global.c (gcry_set_progress_handler): Register a random progress diff --git a/crypto/src/cipher.h b/crypto/src/cipher.h index e97c3686..4c00b8f6 100644 --- a/crypto/src/cipher.h +++ b/crypto/src/cipher.h @@ -45,6 +45,8 @@ #define PUBKEY_ALGO_DSA 17 #define PUBKEY_ALGO_ELGAMAL 20 /* sign and encrypt elgamal */ +#define PUBKEY_FLAG_NO_BLINDING 0x00000001 + #if 0 #define PUBKEY_USAGE_SIG 1 /* key is good for signatures */ #define PUBKEY_USAGE_ENC 2 /* key is good for encryption */ diff --git a/crypto/src/g10lib.h b/crypto/src/g10lib.h index 106c18f7..b8252cae 100644 --- a/crypto/src/g10lib.h +++ b/crypto/src/g10lib.h @@ -1,5 +1,5 @@ /* g10lib.h - internal defintions for libgcrypt - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. * * This header is to be used inside of libgcrypt in place of gcrypt.h. * This way we can better distinguish between internal and external @@ -136,8 +136,12 @@ unsigned pubkey_nbits( int algo, MPI *pkey ); /*-- primegen.c --*/ -MPI _gcry_generate_secret_prime( unsigned nbits ); -MPI _gcry_generate_public_prime( unsigned nbits ); +MPI _gcry_generate_secret_prime (unsigned int nbits, + int (*extra_check)(void*, MPI), + void *extra_check_arg); +MPI _gcry_generate_public_prime (unsigned int nbits, + int (*extra_check)(void*, MPI), + void *extra_check_arg); MPI _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits, MPI g, MPI **factors ); @@ -185,5 +189,18 @@ int strcasecmp (const char *a, const char *b) GCC_ATTR_PURE; #define DIM(v) (sizeof(v)/sizeof((v)[0])) #define DIMof(type,member) DIM(((type *)0)->member) +/* Stack burning. */ + +void _gcry_burn_stack (int bytes); + +/* Digit predicates. */ + +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define octdigitp(p) (*(p) >= '0' && *(p) <= '7') +#define alphap(a) ( (*(a) >= 'A' && *(a) <= 'Z') \ + || (*(a) >= 'a' && *(a) <= 'z')) +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) #endif /* G10LIB_H */ diff --git a/crypto/src/gcrypt.h b/crypto/src/gcrypt.h index e805ce2b..7519cb7a 100644 --- a/crypto/src/gcrypt.h +++ b/crypto/src/gcrypt.h @@ -33,7 +33,7 @@ extern "C" { /* The version of this header should match the one of the library It should not be used by a program because gcry_check_version() should - reurn the same version. The purpose of this macro is to let + return the same version. The purpose of this macro is to let autoconf (using the AM_PATH_GCRYPT macro) check that this header matches the installed library. Note: Do not edit the next line as configure may fix the string here. */ @@ -132,61 +132,82 @@ int gcry_errno(void) _GCRY_GCC_ATTR_PURE; /* Map an error number to a string. */ const char *gcry_strerror (int ec); -/* Codes used with the gcry_control function. */ -enum gcry_ctl_cmds +/* Codes for function dispatchers. */ + +/* Codes for use with gcry_control. These commands influence certain + general functionality of libgcrypt. */ +enum gcry_global_control_cmds + { + GCRYCTL_ENABLE_M_GUARD, + GCRYCTL_ENABLE_QUICK_RANDOM, + GCRYCTL_DUMP_RANDOM_STATS, + GCRYCTL_DUMP_MEMORY_STATS, + GCRYCTL_DUMP_SECMEM_STATS, + GCRYCTL_DROP_PRIVS, + GCRYCTL_DISABLE_SECMEM, + GCRYCTL_INIT_SECMEM, + GCRYCTL_TERM_SECMEM, + GCRYCTL_DISABLE_SECMEM_WARN, + GCRYCTL_SUSPEND_SECMEM_WARN, + GCRYCTL_RESUME_SECMEM_WARN, + GCRYCTL_USE_SECURE_RNDPOOL, + GCRYCTL_SET_VERBOSITY, + GCRYCTL_SET_DEBUG_FLAGS, + GCRYCTL_CLEAR_DEBUG_FLAGS, + GCRYCTL_DISABLE_INTERNAL_LOCKING, + GCRYCTL_INITIALIZATION_FINISHED, + GCRYCTL_INITIALIZATION_FINISHED_P, + GCRYCTL_ANY_INITIALIZATION_P, + }; + +/* Codes for use with gcry_cipher_ctl, gcry_md_ctl and + gcry_pk_ctl. */ +enum gcry_control_cmds { - GCRYCTL_SET_KEY = 1, - GCRYCTL_SET_IV = 2, - GCRYCTL_CFB_SYNC = 3, - GCRYCTL_RESET = 4, /* e.g. for MDs */ - GCRYCTL_FINALIZE = 5, - GCRYCTL_GET_KEYLEN = 6, - GCRYCTL_GET_BLKLEN = 7, - GCRYCTL_TEST_ALGO = 8, - GCRYCTL_IS_SECURE = 9, - GCRYCTL_GET_ASNOID = 10, - GCRYCTL_ENABLE_ALGO = 11, - GCRYCTL_DISABLE_ALGO = 12, - GCRYCTL_DUMP_RANDOM_STATS = 13, - GCRYCTL_DUMP_SECMEM_STATS = 14, - GCRYCTL_GET_ALGO_NPKEY = 15, - GCRYCTL_GET_ALGO_NSKEY = 16, - GCRYCTL_GET_ALGO_NSIGN = 17, - GCRYCTL_GET_ALGO_NENCR = 18, - GCRYCTL_SET_VERBOSITY = 19, - GCRYCTL_SET_DEBUG_FLAGS = 20, - GCRYCTL_CLEAR_DEBUG_FLAGS = 21, - GCRYCTL_USE_SECURE_RNDPOOL= 22, - GCRYCTL_DUMP_MEMORY_STATS = 23, - GCRYCTL_INIT_SECMEM = 24, - GCRYCTL_TERM_SECMEM = 25, - GCRYCTL_DISABLE_SECMEM_WARN = 27, - GCRYCTL_SUSPEND_SECMEM_WARN = 28, - GCRYCTL_RESUME_SECMEM_WARN = 29, - GCRYCTL_DROP_PRIVS = 30, - GCRYCTL_ENABLE_M_GUARD = 31, - GCRYCTL_START_DUMP = 32, - GCRYCTL_STOP_DUMP = 33, - GCRYCTL_GET_ALGO_USAGE = 34, - GCRYCTL_IS_ALGO_ENABLED = 35, - GCRYCTL_DISABLE_INTERNAL_LOCKING = 36, - GCRYCTL_DISABLE_SECMEM = 37, - GCRYCTL_INITIALIZATION_FINISHED = 38, - GCRYCTL_INITIALIZATION_FINISHED_P = 39, - GCRYCTL_ANY_INITIALIZATION_P = 40, - GCRYCTL_SET_CBC_CTS = 41, - GCRYCTL_ENABLE_QUICK_RANDOM = 42 + GCRYCTL_SET_KEY, + GCRYCTL_SET_IV, + GCRYCTL_RESET, + GCRYCTL_CFB_SYNC, + GCRYCTL_SET_CBC_CTS, + GCRYCTL_SET_CBC_MAC, + GCRYCTL_ENABLE_ALGO, /* Not implemented. */ + GCRYCTL_DISABLE_ALGO, + GCRYCTL_FINALIZE, + GCRYCTL_START_DUMP, + GCRYCTL_STOP_DUMP, + }; + +/* Codes for use with gcry_cipher_info and gcry_md_info. */ +enum gcry_info_cmds + { + GCRYCTL_IS_SECURE, + GCRYCTL_IS_ALGO_ENABLED, + }; + +/* Codes for use with gcry_cipher_algo_info, gcry_cipher_md_info and + gcry_cipher_pk_info. */ +enum gcry_algo_info_cmds + { + GCRYCTL_GET_KEYLEN, + GCRYCTL_GET_BLKLEN, + GCRYCTL_TEST_ALGO, + GCRYCTL_GET_ASNOID, + GCRYCTL_GET_ALGO_USAGE, + GCRYCTL_GET_ALGO_NPKEY, + GCRYCTL_GET_ALGO_NSKEY, + GCRYCTL_GET_ALGO_NSIGN, + GCRYCTL_GET_ALGO_NENCR, }; /* Perform various operations defined by CMD. */ -int gcry_control (enum gcry_ctl_cmds CMD, ...); +int gcry_control (enum gcry_global_control_cmds CMD, ...); /* S-expression management. */ -/* The object to represent an S-expression as used with the - public key functions. GcrySexp is the preferrred form. */ +/* The object to represent an S-expression as used with the public key + functions. GcrySexp is the preferred form. */ struct gcry_sexp; typedef struct gcry_sexp *GCRY_SEXP; typedef struct gcry_sexp *GcrySexp; @@ -408,10 +429,9 @@ void gcry_mpi_rshift (GcryMPI x, GcryMPI a, unsigned int n); value. */ GcryMPI gcry_mpi_set_opaque (GcryMPI a, void *p, unsigned int nbits); -/* creturn a pointer to an opaque value stored in A and return its - size in NBITS. Note that the returned pointer is still owned by A - and that the function should never be used for an non-opaque - MPI. */ +/* Return a pointer to an opaque value stored in A and return its size + in NBITS. Note that the returned pointer is still owned by A and + that the function should never be used for an non-opaque MPI. */ void *gcry_mpi_get_opaque (GcryMPI a, unsigned int *nbits); /* Set the FLAG for the big integer A. Currently only the flag @@ -476,7 +496,7 @@ int gcry_mpi_get_flag (GcryMPI a, enum gcry_mpi_flag flag); * * ************************************/ -/* The data object used to hold a handle to an encryption opject. +/* The data object used to hold a handle to an encryption object. GcryCipherHd is the preferred one. */ struct gcry_cipher_handle; typedef struct gcry_cipher_handle *GCRY_CIPHER_HD; @@ -509,7 +529,7 @@ enum gcry_cipher_algos #define GCRY_CIPHER_RIJNDAEL192 GCRY_CIPHER_AES192 #define GCRY_CIPHER_RIJNDAEL256 GCRY_CIPHER_AES256 -/* The supported encryption modes. NOte that not all of them are +/* The supported encryption modes. Note that not all of them are supported for each algorithm. */ enum gcry_cipher_modes { @@ -526,7 +546,8 @@ enum gcry_cipher_flags { GCRY_CIPHER_SECURE = 1, /* Allocate in secure memory. */ GCRY_CIPHER_ENABLE_SYNC = 2, /* Enable CFB sync mode. */ - GCRY_CIPHER_CBC_CTS = 4 /* Enable CBC cipher text stealing (CTS). */ + GCRY_CIPHER_CBC_CTS = 4, /* Enable CBC cipher text stealing (CTS). */ + GCRY_CIPHER_CBC_MAC = 8 /* Enable CBC message auth. code (MAC). */ }; @@ -573,9 +594,9 @@ int gcry_cipher_decrypt (GcryCipherHd h, unsigned char *out, size_t outsize, const unsigned char *in, size_t inlen); -/* Set key K of length L for the cipher handle H. - (We have to cast away a const char* here - this catch-all ctl - function was probably not the best choice) */ +/* Set key K of length L for the cipher handle H. (We have to cast + away a const char* here - this catch-all ctl function was probably + not the best choice) */ #define gcry_cipher_setkey(h,k,l) gcry_cipher_ctl( (h), GCRYCTL_SET_KEY, \ (char*)(k), (l) ) @@ -583,7 +604,10 @@ int gcry_cipher_decrypt (GcryCipherHd h, #define gcry_cipher_setiv(h,k,l) gcry_cipher_ctl( (h), GCRYCTL_SET_IV, \ (char*)(k), (l) ) -/* Perform the the OppenPGP sync operation if this is enabled for the +/* Reset the handle to the state after open. */ +#define gcry_cipher_reset(h) gcry_cipher_ctl ((h), GCRYCTL_RESET, NULL, 0) + +/* Perform the the OpenPGP sync operation if this is enabled for the cipher handle H. */ #define gcry_cipher_sync(h) gcry_cipher_ctl( (h), GCRYCTL_CFB_SYNC, \ NULL, 0 ) @@ -742,7 +766,7 @@ int gcry_md_enable( GcryMDHd hd, int algo ); /* Create a new digest object as an exact copy of the object HD. */ GcryMDHd gcry_md_copy (GcryMDHd hd); -/* Reset the digest object HD to its initail state. */ +/* Reset the digest object HD to its initial state. */ void gcry_md_reset (GcryMDHd hd); /* Perform various operations on the digets object HD. */ @@ -769,7 +793,7 @@ void gcry_md_hash_buffer (int algo, void *digest, if more than one algorithm is enabled in HD. */ int gcry_md_get_algo (GcryMDHd hd); -/* Retrieved the length in bytes of the digest yielded by algorithm +/* Retrieve the length in bytes of the digest yielded by algorithm ALGO. */ unsigned int gcry_md_get_algo_dlen (int algo); @@ -887,7 +911,7 @@ void gcry_mpi_randomize (GcryMPI w, * * ************************************/ -/* Log leveles used by the internal logging facility. */ +/* Log levels used by the internal logging facility. */ enum gcry_log_levels { GCRY_LOG_CONT = 0, /* continue the last log line */ diff --git a/crypto/src/global.c b/crypto/src/global.c index 4985d01d..5d42e482 100644 --- a/crypto/src/global.c +++ b/crypto/src/global.c @@ -138,7 +138,7 @@ gcry_check_version( const char *req_version ) int -gcry_control( enum gcry_ctl_cmds cmd, ... ) +gcry_control( enum gcry_global_control_cmds cmd, ... ) { static int init_finished = 0; va_list arg_ptr ; @@ -193,15 +193,18 @@ gcry_control( enum gcry_ctl_cmds cmd, ... ) break; case GCRYCTL_DISABLE_SECMEM_WARN: - _gcry_secmem_set_flags( (_gcry_secmem_get_flags() | 1) ); + _gcry_secmem_set_flags ((_gcry_secmem_get_flags () + | GCRY_SECMEM_FLAG_NO_WARNING)); break; case GCRYCTL_SUSPEND_SECMEM_WARN: - _gcry_secmem_set_flags( (_gcry_secmem_get_flags() | 2) ); + _gcry_secmem_set_flags ((_gcry_secmem_get_flags () + | GCRY_SECMEM_FLAG_SUSPEND_WARNING)); break; case GCRYCTL_RESUME_SECMEM_WARN: - _gcry_secmem_set_flags( (_gcry_secmem_get_flags() & ~2) ); + _gcry_secmem_set_flags ((_gcry_secmem_get_flags () + & ~GCRY_SECMEM_FLAG_SUSPEND_WARNING)); break; case GCRYCTL_USE_SECURE_RNDPOOL: diff --git a/crypto/src/misc.c b/crypto/src/misc.c index 178eab5d..12f37c01 100644 --- a/crypto/src/misc.c +++ b/crypto/src/misc.c @@ -1,5 +1,5 @@ /* misc.c - * Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -28,7 +28,7 @@ #include "g10lib.h" -static int verbosity_level = 0; /* fixme: add a function to set it */ +static int verbosity_level = 0; static void (*fatal_error_handler)(void*,int, const char*) = NULL; static void *fatal_error_handler_value = 0; @@ -193,7 +193,7 @@ _gcry_log_fatal( const char *fmt, ... ) va_start( arg_ptr, fmt ) ; _gcry_logv( GCRY_LOG_FATAL, fmt, arg_ptr ); va_end(arg_ptr); - abort(); /* never called, bugs it makes the compiler happy */ + abort(); /* never called, but it makes the compiler happy */ } void @@ -204,7 +204,7 @@ _gcry_log_bug( const char *fmt, ... ) va_start( arg_ptr, fmt ) ; _gcry_logv( GCRY_LOG_BUG, fmt, arg_ptr ); va_end(arg_ptr); - abort(); /* never called, bugs it makes the compiler happy */ + abort(); /* never called, but it makes the compiler happy */ } void @@ -229,3 +229,14 @@ _gcry_log_printf (const char *fmt, ...) va_end(arg_ptr); } } + +void +_gcry_burn_stack (int bytes) +{ + char buf[64]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + _gcry_burn_stack (bytes); +} diff --git a/crypto/src/secmem.c b/crypto/src/secmem.c index 5c3ad703..7d0b6819 100644 --- a/crypto/src/secmem.c +++ b/crypto/src/secmem.c @@ -1,5 +1,5 @@ /* secmem.c - memory allocation from a secure heap - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -42,6 +42,7 @@ #endif #define DEFAULT_POOLSIZE 16384 +#define DEFAULT_PAGESIZE 4096 typedef struct memblock_struct MEMBLOCK; struct memblock_struct { @@ -170,7 +171,7 @@ init_pool( size_t n) #ifdef HAVE_GETPAGESIZE pgsize = getpagesize(); #else - pgsize = 4096; + pgsize = DEFAULT_PAGESIZE; #endif #if HAVE_MMAP @@ -226,8 +227,8 @@ _gcry_secmem_set_flags( unsigned flags ) { int was_susp = suspend_warning; - no_warning = flags & 1; - suspend_warning = flags & 2; + no_warning = flags & GCRY_SECMEM_FLAG_NO_WARNING; + suspend_warning = flags & GCRY_SECMEM_FLAG_SUSPEND_WARNING; /* and now issue the warning if it is not longer suspended */ if( was_susp && !suspend_warning && show_warning ) { @@ -241,8 +242,8 @@ _gcry_secmem_get_flags(void) { unsigned flags; - flags = no_warning ? 1:0; - flags |= suspend_warning ? 2:0; + flags = no_warning ? GCRY_SECMEM_FLAG_NO_WARNING : 0; + flags |= suspend_warning ? GCRY_SECMEM_FLAG_SUSPEND_WARNING : 0; return flags; } diff --git a/crypto/src/secmem.h b/crypto/src/secmem.h index d3e9995e..553b3858 100644 --- a/crypto/src/secmem.h +++ b/crypto/src/secmem.h @@ -1,5 +1,5 @@ /* secmem.h - internal definitions for secmem - * Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -22,14 +22,17 @@ #define G10_SECMEM_H 1 void _gcry_secmem_init (size_t npool); -void _gcry_secmem_ter (void); +void _gcry_secmem_term (void); void *_gcry_secmem_malloc (size_t size) GCC_ATTR_MALLOC; void *_gcry_secmem_realloc (void *a, size_t newsize); void _gcry_secmem_free (void *a); void _gcry_secmem_dump_stats (void); void _gcry_secmem_set_flags (unsigned flags); unsigned _gcry_secmem_get_flags(void) GCC_ATTR_PURE; - int _gcry_private_is_secure (const void *p) GCC_ATTR_PURE; +/* Flags for _gcry_secmem_{set,get}_flags. */ +#define GCRY_SECMEM_FLAG_NO_WARNING 0x00000001 +#define GCRY_SECMEM_FLAG_SUSPEND_WARNING 0x00000002 + #endif /* G10_SECMEM_H */ diff --git a/crypto/src/sexp.c b/crypto/src/sexp.c index bda2484f..4f8d449e 100644 --- a/crypto/src/sexp.c +++ b/crypto/src/sexp.c @@ -44,13 +44,6 @@ struct gcry_sexp { #define ST_OPEN 3 #define ST_CLOSE 4 -#define digitp(p) (*(p) >= '0' && *(p) <= '9') -#define octdigitp(p) (*(p) >= '0' && *(p) <= '7') -#define alphap(a) ( (*(a) >= 'A' && *(a) <= 'Z') \ - || (*(a) >= 'a' && *(a) <= 'z')) -#define hexdigitp(a) (digitp (a) \ - || (*(a) >= 'A' && *(a) <= 'F') \ - || (*(a) >= 'a' && *(a) <= 'f')) /* the atoi macros assume that the buffer has only valid digits */ #define atoi_1(p) (*(p) - '0' ) #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ @@ -1028,7 +1021,7 @@ sexp_sscan( GCRY_SEXP *retsexp, size_t *erroff , else if ( percent ) { if ( *p == 'm' ) { /* insert an MPI */ GCRY_MPI m = va_arg (arg_ptr, GCRY_MPI); - size_t nm; + size_t nm = 0; if ( gcry_mpi_print( GCRYMPI_FMT_STD, NULL, &nm, m ) ) BUG (); diff --git a/crypto/tests/ChangeLog b/crypto/tests/ChangeLog index 08c74c58..bc71777a 100644 --- a/crypto/tests/ChangeLog +++ b/crypto/tests/ChangeLog @@ -1,3 +1,25 @@ +2003-03-26 Moritz Schulte + + * Makefile.am (TESTS): Added pubkey. + + * pubkey.c: New file. + +2003-03-22 Simon Josefsson + + * basic.c (check_cbc_mac_cipher): New. + (main): Use it. + +2003-03-19 Werner Koch + + * keygen.c (check_rsa_keys): Don't expect an exponent when asking + for e=0. + (check_generated_rsa_key): Just print exponent if EXPECTED_E is 0. + +2003-03-02 Moritz Schulte + + * basic.c (check_one_cipher): Use gcry_cipher_reset() instead of + gcry_cipher_close(), gcry_cipher_open and gcry_cipher_setkey(). + 2003-01-23 Werner Koch * keygen.c: New. diff --git a/crypto/tests/Makefile.am b/crypto/tests/Makefile.am index aa9dc523..83f7ea0e 100644 --- a/crypto/tests/Makefile.am +++ b/crypto/tests/Makefile.am @@ -21,7 +21,7 @@ # TESTS_ENVIRONMENT = -TESTS = basic tsexp keygen +TESTS = basic tsexp keygen pubkey EXTRA_DIST = @@ -29,10 +29,3 @@ INCLUDES = -I$(top_srcdir)/src LDADD = ../src/libgcrypt.la noinst_PROGRAMS = $(TESTS) - - - - - - - diff --git a/crypto/tests/basic.c b/crypto/tests/basic.c index fabe80d2..cb3bd025 100644 --- a/crypto/tests/basic.c +++ b/crypto/tests/basic.c @@ -1,5 +1,5 @@ /* basic.c - basic regression tests - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -88,6 +88,86 @@ die ( const char *format, ... ) #define MAX_DATA_LEN 100 static void +check_cbc_mac_cipher (void) +{ + struct tv { + int algo; + char key[MAX_DATA_LEN]; + char plaintext[MAX_DATA_LEN]; + size_t plaintextlen; + char mac[MAX_DATA_LEN]; + } tv[] = { + { GCRY_CIPHER_AES, + "chicken teriyaki", + "This is a sample plaintext for CBC MAC of sixtyfour bytes.......", 0, + "\x23\x8f\x6d\xc7\x53\x6a\x62\x97\x11\xc4\xa5\x16\x43\xea\xb0\xb6" }, + { GCRY_CIPHER_3DES, + "abcdefghABCDEFGH01234567", + "This is a sample plaintext for CBC MAC of sixtyfour bytes.......", 0, + "\x5c\x11\xf0\x01\x47\xbd\x3d\x3a" }, + { GCRY_CIPHER_DES, + "abcdefgh", + "This is a sample plaintext for CBC MAC of sixtyfour bytes.......", 0, + "\xfa\x4b\xdf\x9d\xfa\xab\x01\x70" } + }; + GCRY_CIPHER_HD hd; + char out[MAX_DATA_LEN]; + int i; + + for (i = 0; i < sizeof(tv) / sizeof(tv[0]); i++) + { + hd = gcry_cipher_open (tv[i].algo, + GCRY_CIPHER_MODE_CBC, + GCRY_CIPHER_CBC_MAC); + if (!hd) { + fail ("cbc-mac algo %d, grcy_open_cipher failed: %s\n", + tv[i].algo, gcry_strerror (-1) ); + return; + } + + if (gcry_cipher_setkey (hd, tv[i].key, + gcry_cipher_get_algo_keylen (tv[i].algo))) { + fail ("cbc-mac algo %d, gcry_cipher_setkey failed: %s\n", + tv[i].algo, gcry_strerror (-1) ); + gcry_cipher_close (hd); + return; + } + + if (gcry_cipher_setiv (hd, NULL, 0)) { + fail ("cbc-mac algo %d, gcry_cipher_setiv failed: %s\n", + tv[i].algo, gcry_strerror (-1) ); + gcry_cipher_close (hd); + return; + } + + if ( gcry_cipher_encrypt (hd, + out, gcry_cipher_get_algo_blklen(tv[i].algo), + tv[i].plaintext, + tv[i].plaintextlen ? + tv[i].plaintextlen : + strlen(tv[i].plaintext))) { + fail ("cbc-mac algo %d, gcry_cipher_encrypt failed: %s\n", + tv[i].algo, gcry_strerror (-1) ); + gcry_cipher_close (hd); + return; + } + +#if 0 + { int j; + for (j=0; j < gcry_cipher_get_algo_blklen(tv[i].algo); j++) + printf("\\x%02x", out[j] & 0xFF); + printf("\n"); + } +#endif + + if ( memcmp (tv[i].mac, out, gcry_cipher_get_algo_blklen(tv[i].algo)) ) + fail ("cbc-mac algo %d, encrypt mismatch entry %d\n", tv[i].algo, i); + + gcry_cipher_close (hd); + } +} + +static void check_aes128_cbc_cts_cipher () { char key[128/8] = "chicken teriyaki"; @@ -210,21 +290,8 @@ check_one_cipher (int algo, int mode, int flags) return; } - gcry_cipher_close (hd); - hd = gcry_cipher_open (algo, mode, flags); - if (!hd) { - fail ("algo %d, mode %d, grcy_open_cipher failed: %s\n", - algo, mode, gcry_strerror (-1) ); - return; - } + gcry_cipher_reset (hd); - if (gcry_cipher_setkey (hd, key, keylen)) { - fail ("algo %d, mode %d, gcry_cipher_setkey[2] failed: %s\n", - algo, mode, gcry_strerror (-1) ); - gcry_cipher_close (hd); - return; - } - if ( gcry_cipher_decrypt (hd, in, 16, out, 16)) { fail ("algo %d, mode %d, gcry_cipher_decrypt failed: %s\n", algo, mode, gcry_strerror (-1) ); @@ -605,15 +672,15 @@ main (int argc, char **argv) else if (argc > 1 && !strcmp (argv[1], "--debug")) verbose = debug = 1; - /*gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING,0);*/ - gcry_control (GCRYCTL_DISABLE_SECMEM, 0); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); if (debug) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); check_ciphers (); check_aes128_cbc_cts_cipher (); + check_cbc_mac_cipher (); check_digests (); check_pubkey (); diff --git a/crypto/tests/keygen.c b/crypto/tests/keygen.c index 8554118b..a65a0c39 100644 --- a/crypto/tests/keygen.c +++ b/crypto/tests/keygen.c @@ -77,7 +77,7 @@ check_generated_rsa_key (GcrySexp key, unsigned long expected_e) { GcrySexp skey, pkey, list; - pkey = gcry_sexp_find_token (key, "public-key", 0); + pkey = gcry_sexp_find_token (key, "public-key", 0); if (!pkey) fail ("public part missing in return value\n"); else @@ -87,7 +87,12 @@ check_generated_rsa_key (GcrySexp key, unsigned long expected_e) list = gcry_sexp_find_token (pkey, "e", 0); if (!list || !(e=gcry_sexp_nth_mpi (list, 1, 0)) ) fail ("public exponent not found\n"); - else if (gcry_mpi_cmp_ui (e, expected_e)) + else if (!expected_e) + { + if (verbose) + print_mpi ("e", e); + } + else if ( gcry_mpi_cmp_ui (e, expected_e)) { print_mpi ("e", e); fail ("public exponent is not %lu\n", expected_e); @@ -152,7 +157,7 @@ check_rsa_keys (void) gcry_sexp_release (key); if (verbose) - fprintf (stderr, "creating 512 bit RSA key with default e=41\n"); + fprintf (stderr, "creating 512 bit RSA key with default e\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (rsa\n" @@ -166,7 +171,7 @@ check_rsa_keys (void) if (rc) die ("error generating RSA key: %s\n", gcry_strerror (rc)); - check_generated_rsa_key (key, 41); + check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */ gcry_sexp_release (key); } @@ -184,9 +189,9 @@ main (int argc, char **argv) else if (argc > 1 && !strcmp (argv[1], "--debug")) verbose = debug = 1; - gcry_control (GCRYCTL_DISABLE_SECMEM, 0); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); if (debug) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); @@ -196,3 +201,4 @@ main (int argc, char **argv) return error_count? 1:0; } + diff --git a/crypto/tests/pubkey.c b/crypto/tests/pubkey.c new file mode 100644 index 00000000..1c2f7df9 --- /dev/null +++ b/crypto/tests/pubkey.c @@ -0,0 +1,148 @@ +/* pubkey.c - Public key encryption/decryption tests + * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include + + +#include "../src/gcrypt.h" + +/* Sample RSA keys, taken from basic.c. */ + +static const char sample_private_key_1[] = +"(private-key\n" +" (rsa\n" +" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" + "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" + "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" + "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" +" (e #010001#)\n" +" (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11" + "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD" + "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21" + "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n" +" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" + "fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)\n" +" (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9" + "35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)\n" +" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" + "ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)\n" +" )\n" +")\n"; + +static const char sample_public_key_1[] = +"(public-key\n" +" (rsa\n" +" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" + "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" + "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" + "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" +" (e #010001#)\n" +" )\n" +")\n"; + +#define RANDOM_DATA_NBITS 800 + +static int verbose; + +static void +die (const char *format, ...) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + exit (1); +} + +void +check_run (void) +{ + GcrySexp skey, pkey, plain0, plain1, cipher, l; + GcryMPI x0, x1; + int rc; + + /* Construct s-exp's for keys. */ + rc = gcry_sexp_sscan (&skey, NULL, sample_private_key_1, + strlen (sample_private_key_1)); + if (!rc) + rc = gcry_sexp_sscan (&pkey, NULL, sample_public_key_1, + strlen (sample_public_key_1)); + if (rc) + die ("converting sample keys failed: %s\n", gcry_strerror (rc)); + + /* Create random data. */ + x0 = gcry_mpi_new (RANDOM_DATA_NBITS); + gcry_mpi_randomize (x0, RANDOM_DATA_NBITS, GCRY_WEAK_RANDOM); + rc = gcry_sexp_build (&plain0, NULL, "(data (flags raw) (value %m))", + x0); + if (rc) + die ("converting data for encryption failed: %s\n", + gcry_strerror (rc)); + + /* Encrypt data. */ + rc = gcry_pk_encrypt (&cipher, plain0, pkey); + gcry_sexp_release (plain0); + if (rc) + die ("encryption failed: %s\n", gcry_strerror (rc)); + + /* Decrypt data. */ + rc = gcry_pk_decrypt (&plain1, cipher, skey); + gcry_sexp_release (cipher); + if (rc) + die ("decryption failed: %s\n", gcry_strerror (rc)); + + /* Extract decrypted data. */ + l = gcry_sexp_find_token (plain1, "value", 0); + gcry_sexp_release (plain1); + x1 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l); + + /* Compare. */ + if (gcry_mpi_cmp (x0, x1)) + die ("data corrupted\n"); +} + +int +main (int argc, char **argv) +{ + int debug = 0; + int i = 10; + + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + verbose = debug = 1; + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); + + for (; i > 0; i--) + check_run (); + + return 0; +} -- 2.11.4.GIT