From 1342185e333cb8139b7a70b7fe43571bcc2716a7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 11 Nov 2010 11:27:33 +1100 Subject: s4:heimdal: import lorikeet-heimdal-201011102149 (commit 5734d03c20e104c8f45533d07f2a2cbbd3224f29) --- source4/heimdal/kdc/default_config.c | 44 +- source4/heimdal/kuser/kinit.c | 5 +- source4/heimdal/lib/asn1/asn1parse.c | 3042 ------------------ source4/heimdal/lib/asn1/asn1parse.h | 255 -- source4/heimdal/lib/asn1/asn1parse.y | 28 +- source4/heimdal/lib/asn1/gen_decode.c | 8 +- source4/heimdal/lib/asn1/lex.h | 2 +- source4/heimdal/lib/asn1/lex.l | 10 +- source4/heimdal/lib/asn1/symbol.c | 2 +- source4/heimdal/lib/com_err/lex.h | 2 +- source4/heimdal/lib/com_err/lex.l | 4 +- source4/heimdal/lib/com_err/parse.y | 2 +- source4/heimdal/lib/gssapi/krb5/init_sec_context.c | 27 +- source4/heimdal/lib/hcrypto/dh-imath.c | 254 -- source4/heimdal/lib/hcrypto/dh-ltm.c | 41 +- source4/heimdal/lib/hcrypto/dh.c | 8 +- source4/heimdal/lib/hcrypto/dh.h | 2 - source4/heimdal/lib/hcrypto/engine.c | 20 - source4/heimdal/lib/hcrypto/imath/LICENSE | 21 - source4/heimdal/lib/hcrypto/imath/imath.c | 3353 -------------------- source4/heimdal/lib/hcrypto/imath/imath.h | 231 -- source4/heimdal/lib/hcrypto/imath/iprime.c | 189 -- source4/heimdal/lib/hcrypto/imath/iprime.h | 51 - source4/heimdal/lib/hcrypto/rsa-imath.c | 688 ---- source4/heimdal/lib/hcrypto/rsa.c | 17 +- source4/heimdal/lib/hcrypto/rsa.h | 2 - source4/heimdal/lib/hcrypto/sha.h | 6 + source4/heimdal/lib/hcrypto/sha512.c | 108 +- source4/heimdal/lib/hx509/cms.c | 14 +- source4/heimdal/lib/hx509/collector.c | 1 + source4/heimdal/lib/hx509/crypto.c | 103 +- source4/heimdal/lib/hx509/hx509.h | 8 + source4/heimdal/lib/hx509/hx509_err.et | 1 + source4/heimdal/lib/hx509/ks_file.c | 3 +- source4/heimdal/lib/hx509/ks_p12.c | 1 + source4/heimdal/lib/krb5/context.c | 26 +- source4/heimdal/lib/krb5/crypto.c | 2874 +---------------- source4/heimdal/lib/krb5/data.c | 19 + source4/heimdal/lib/krb5/get_cred.c | 96 +- source4/heimdal/lib/krb5/krb5_locl.h | 5 + source4/heimdal/lib/krb5/misc.c | 7 + source4/heimdal/lib/krb5/mit_glue.c | 3 +- source4/heimdal/lib/krb5/pac.c | 157 +- source4/heimdal/lib/krb5/plugin.c | 257 ++ source4/heimdal/lib/krb5/store.c | 24 - source4/heimdal/lib/ntlm/heimntlm.h | 21 +- source4/heimdal/lib/ntlm/ntlm.c | 707 ++++- 47 files changed, 1450 insertions(+), 11299 deletions(-) delete mode 100644 source4/heimdal/lib/asn1/asn1parse.c delete mode 100644 source4/heimdal/lib/asn1/asn1parse.h delete mode 100644 source4/heimdal/lib/hcrypto/dh-imath.c delete mode 100644 source4/heimdal/lib/hcrypto/imath/LICENSE delete mode 100644 source4/heimdal/lib/hcrypto/imath/imath.c delete mode 100644 source4/heimdal/lib/hcrypto/imath/imath.h delete mode 100644 source4/heimdal/lib/hcrypto/imath/iprime.c delete mode 100644 source4/heimdal/lib/hcrypto/imath/iprime.h delete mode 100644 source4/heimdal/lib/hcrypto/rsa-imath.c (limited to 'source4/heimdal') diff --git a/source4/heimdal/kdc/default_config.c b/source4/heimdal/kdc/default_config.c index 118bdf97aa..f745183e51 100644 --- a/source4/heimdal/kdc/default_config.c +++ b/source4/heimdal/kdc/default_config.c @@ -258,37 +258,43 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) 0, "kdc", "pkinit_dh_min_bits", NULL); + *config = c; + return 0; +} + +krb5_error_code +krb5_kdc_pkinit_config(krb5_context context, krb5_kdc_configuration *config) +{ +#ifdef PKINIT #ifdef __APPLE__ - c->enable_pkinit = 1; + config->enable_pkinit = 1; - if (c->pkinit_kdc_identity == NULL) { - if (c->pkinit_kdc_friendly_name == NULL) - c->pkinit_kdc_friendly_name = + if (config->pkinit_kdc_identity == NULL) { + if (config->pkinit_kdc_friendly_name == NULL) + config->pkinit_kdc_friendly_name = strdup("O=System Identity,CN=com.apple.kerberos.kdc"); - c->pkinit_kdc_identity = strdup("KEYCHAIN:"); + config->pkinit_kdc_identity = strdup("KEYCHAIN:"); } - if (c->pkinit_kdc_anchors == NULL) - c->pkinit_kdc_anchors = strdup("KEYCHAIN:"); + if (config->pkinit_kdc_anchors == NULL) + config->pkinit_kdc_anchors = strdup("KEYCHAIN:"); -#endif +#endif /* __APPLE__ */ - if (c->enable_pkinit) { - if (c->pkinit_kdc_identity == NULL) + if (config->enable_pkinit) { + if (config->pkinit_kdc_identity == NULL) krb5_errx(context, 1, "pkinit enabled but no identity"); - if (c->pkinit_kdc_anchors == NULL) + if (config->pkinit_kdc_anchors == NULL) krb5_errx(context, 1, "pkinit enabled but no X509 anchors"); - krb5_kdc_pk_initialize(context, c, - c->pkinit_kdc_identity, - c->pkinit_kdc_anchors, - c->pkinit_kdc_cert_pool, - c->pkinit_kdc_revoke); + krb5_kdc_pk_initialize(context, config, + config->pkinit_kdc_identity, + config->pkinit_kdc_anchors, + config->pkinit_kdc_cert_pool, + config->pkinit_kdc_revoke); } - *config = c; - - return 0; +#endif /* PKINIT */ } diff --git a/source4/heimdal/kuser/kinit.c b/source4/heimdal/kuser/kinit.c index e6201fbbc0..11e364980d 100644 --- a/source4/heimdal/kuser/kinit.c +++ b/source4/heimdal/kuser/kinit.c @@ -107,7 +107,10 @@ static struct getargs args[] = { { "cache", 'c', arg_string, &cred_cache, NP_("credentials cache", ""), "cachename" }, - { "forwardable", 'f', arg_negative_flag, &forwardable_flag, + { "forwardable", 0, arg_negative_flag, &forwardable_flag, + NP_("get tickets not forwardable", "")}, + + { NULL, 'f', arg_flag, &forwardable_flag, NP_("get forwardable tickets", "")}, { "keytab", 't', arg_string, &keytab_str, diff --git a/source4/heimdal/lib/asn1/asn1parse.c b/source4/heimdal/lib/asn1/asn1parse.c deleted file mode 100644 index 4c2ae26d85..0000000000 --- a/source4/heimdal/lib/asn1/asn1parse.c +++ /dev/null @@ -1,3042 +0,0 @@ - -/* A Bison parser, made by GNU Bison 2.4.1. */ - -/* Skeleton implementation for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "2.4.1" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - -/* Using locations. */ -#define YYLSP_NEEDED 0 - - - -/* Copy the first part of user declarations. */ - -/* Line 189 of yacc.c */ -#line 38 "heimdal/lib/asn1/asn1parse.y" - - -#include - -#include -#include -#include -#include "symbol.h" -#include "lex.h" -#include "gen_locl.h" -#include "der.h" - -RCSID("$Id$"); - -static Type *new_type (Typetype t); -static struct constraint_spec *new_constraint_spec(enum ctype); -static Type *new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype); -void yyerror (const char *); -static struct objid *new_objid(const char *label, int value); -static void add_oid_to_tail(struct objid *, struct objid *); -static void fix_labels(Symbol *s); - -struct string_list { - char *string; - struct string_list *next; -}; - - - -/* Line 189 of yacc.c */ -#line 103 "heimdal/lib/asn1/asn1parse.y" - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 -#endif - - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - kw_ABSENT = 258, - kw_ABSTRACT_SYNTAX = 259, - kw_ALL = 260, - kw_APPLICATION = 261, - kw_AUTOMATIC = 262, - kw_BEGIN = 263, - kw_BIT = 264, - kw_BMPString = 265, - kw_BOOLEAN = 266, - kw_BY = 267, - kw_CHARACTER = 268, - kw_CHOICE = 269, - kw_CLASS = 270, - kw_COMPONENT = 271, - kw_COMPONENTS = 272, - kw_CONSTRAINED = 273, - kw_CONTAINING = 274, - kw_DEFAULT = 275, - kw_DEFINITIONS = 276, - kw_EMBEDDED = 277, - kw_ENCODED = 278, - kw_END = 279, - kw_ENUMERATED = 280, - kw_EXCEPT = 281, - kw_EXPLICIT = 282, - kw_EXPORTS = 283, - kw_EXTENSIBILITY = 284, - kw_EXTERNAL = 285, - kw_FALSE = 286, - kw_FROM = 287, - kw_GeneralString = 288, - kw_GeneralizedTime = 289, - kw_GraphicString = 290, - kw_IA5String = 291, - kw_IDENTIFIER = 292, - kw_IMPLICIT = 293, - kw_IMPLIED = 294, - kw_IMPORTS = 295, - kw_INCLUDES = 296, - kw_INSTANCE = 297, - kw_INTEGER = 298, - kw_INTERSECTION = 299, - kw_ISO646String = 300, - kw_MAX = 301, - kw_MIN = 302, - kw_MINUS_INFINITY = 303, - kw_NULL = 304, - kw_NumericString = 305, - kw_OBJECT = 306, - kw_OCTET = 307, - kw_OF = 308, - kw_OPTIONAL = 309, - kw_ObjectDescriptor = 310, - kw_PATTERN = 311, - kw_PDV = 312, - kw_PLUS_INFINITY = 313, - kw_PRESENT = 314, - kw_PRIVATE = 315, - kw_PrintableString = 316, - kw_REAL = 317, - kw_RELATIVE_OID = 318, - kw_SEQUENCE = 319, - kw_SET = 320, - kw_SIZE = 321, - kw_STRING = 322, - kw_SYNTAX = 323, - kw_T61String = 324, - kw_TAGS = 325, - kw_TRUE = 326, - kw_TYPE_IDENTIFIER = 327, - kw_TeletexString = 328, - kw_UNION = 329, - kw_UNIQUE = 330, - kw_UNIVERSAL = 331, - kw_UTCTime = 332, - kw_UTF8String = 333, - kw_UniversalString = 334, - kw_VideotexString = 335, - kw_VisibleString = 336, - kw_WITH = 337, - RANGE = 338, - EEQUAL = 339, - ELLIPSIS = 340, - IDENTIFIER = 341, - referencename = 342, - STRING = 343, - NUMBER = 344 - }; -#endif -/* Tokens. */ -#define kw_ABSENT 258 -#define kw_ABSTRACT_SYNTAX 259 -#define kw_ALL 260 -#define kw_APPLICATION 261 -#define kw_AUTOMATIC 262 -#define kw_BEGIN 263 -#define kw_BIT 264 -#define kw_BMPString 265 -#define kw_BOOLEAN 266 -#define kw_BY 267 -#define kw_CHARACTER 268 -#define kw_CHOICE 269 -#define kw_CLASS 270 -#define kw_COMPONENT 271 -#define kw_COMPONENTS 272 -#define kw_CONSTRAINED 273 -#define kw_CONTAINING 274 -#define kw_DEFAULT 275 -#define kw_DEFINITIONS 276 -#define kw_EMBEDDED 277 -#define kw_ENCODED 278 -#define kw_END 279 -#define kw_ENUMERATED 280 -#define kw_EXCEPT 281 -#define kw_EXPLICIT 282 -#define kw_EXPORTS 283 -#define kw_EXTENSIBILITY 284 -#define kw_EXTERNAL 285 -#define kw_FALSE 286 -#define kw_FROM 287 -#define kw_GeneralString 288 -#define kw_GeneralizedTime 289 -#define kw_GraphicString 290 -#define kw_IA5String 291 -#define kw_IDENTIFIER 292 -#define kw_IMPLICIT 293 -#define kw_IMPLIED 294 -#define kw_IMPORTS 295 -#define kw_INCLUDES 296 -#define kw_INSTANCE 297 -#define kw_INTEGER 298 -#define kw_INTERSECTION 299 -#define kw_ISO646String 300 -#define kw_MAX 301 -#define kw_MIN 302 -#define kw_MINUS_INFINITY 303 -#define kw_NULL 304 -#define kw_NumericString 305 -#define kw_OBJECT 306 -#define kw_OCTET 307 -#define kw_OF 308 -#define kw_OPTIONAL 309 -#define kw_ObjectDescriptor 310 -#define kw_PATTERN 311 -#define kw_PDV 312 -#define kw_PLUS_INFINITY 313 -#define kw_PRESENT 314 -#define kw_PRIVATE 315 -#define kw_PrintableString 316 -#define kw_REAL 317 -#define kw_RELATIVE_OID 318 -#define kw_SEQUENCE 319 -#define kw_SET 320 -#define kw_SIZE 321 -#define kw_STRING 322 -#define kw_SYNTAX 323 -#define kw_T61String 324 -#define kw_TAGS 325 -#define kw_TRUE 326 -#define kw_TYPE_IDENTIFIER 327 -#define kw_TeletexString 328 -#define kw_UNION 329 -#define kw_UNIQUE 330 -#define kw_UNIVERSAL 331 -#define kw_UTCTime 332 -#define kw_UTF8String 333 -#define kw_UniversalString 334 -#define kw_VideotexString 335 -#define kw_VisibleString 336 -#define kw_WITH 337 -#define RANGE 338 -#define EEQUAL 339 -#define ELLIPSIS 340 -#define IDENTIFIER 341 -#define referencename 342 -#define STRING 343 -#define NUMBER 344 - - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE -{ - -/* Line 214 of yacc.c */ -#line 67 "heimdal/lib/asn1/asn1parse.y" - - int constant; - struct value *value; - struct range *range; - char *name; - Type *type; - Member *member; - struct objid *objid; - char *defval; - struct string_list *sl; - struct tagtype tag; - struct memhead *members; - struct constraint_spec *constraint_spec; - - - -/* Line 214 of yacc.c */ -#line 334 "heimdal/lib/asn1/asn1parse.y" -} YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - - -/* Copy the second part of user declarations. */ - - -/* Line 264 of yacc.c */ -#line 346 "heimdal/lib/asn1/asn1parse.y" - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char yytype_int8; -#else -typedef short int yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short int yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short int yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned int -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) -# endif -# endif -# ifndef YY_ -# define YY_(msgid) msgid -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) -#else -# define YYUSE(e) /* empty */ -#endif - -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(n) (n) -#else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int yyi) -#else -static int -YYID (yyi) - int yyi; -#endif -{ - return yyi; -} -#endif - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined _STDLIB_H \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif - -/* Relocate 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_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (YYID (0)) - -#endif - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 6 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 203 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 98 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 69 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 140 -/* YYNRULES -- Number of states. */ -#define YYNSTATES 220 - -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 344 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 92, 93, 2, 2, 91, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 90, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 96, 2, 97, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 94, 2, 95, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89 -}; - -#if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint16 yyprhs[] = -{ - 0, 0, 3, 13, 16, 19, 22, 23, 26, 27, - 31, 32, 36, 37, 39, 40, 42, 45, 50, 54, - 57, 58, 60, 63, 65, 67, 71, 73, 77, 79, - 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, - 101, 103, 105, 107, 109, 111, 113, 119, 125, 131, - 135, 137, 140, 145, 147, 151, 155, 160, 165, 167, - 170, 176, 179, 183, 185, 186, 189, 194, 198, 203, - 208, 212, 216, 221, 223, 225, 227, 229, 231, 234, - 238, 240, 242, 244, 247, 251, 257, 262, 266, 271, - 272, 274, 276, 278, 279, 281, 283, 288, 290, 292, - 294, 296, 298, 300, 302, 304, 306, 308, 312, 316, - 319, 321, 324, 328, 330, 334, 339, 341, 342, 346, - 347, 350, 355, 357, 359, 361, 363, 365, 367, 369, - 371, 373, 375, 377, 379, 381, 383, 385, 387, 389, - 391 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int16 yyrhs[] = -{ - 99, 0, -1, 86, 152, 21, 100, 101, 84, 8, - 102, 24, -1, 27, 70, -1, 38, 70, -1, 7, - 70, -1, -1, 29, 39, -1, -1, 107, 103, 108, - -1, -1, 40, 104, 90, -1, -1, 105, -1, -1, - 106, -1, 105, 106, -1, 110, 32, 86, 152, -1, - 28, 110, 90, -1, 28, 5, -1, -1, 109, -1, - 109, 108, -1, 111, -1, 144, -1, 86, 91, 110, - -1, 86, -1, 86, 84, 112, -1, 113, -1, 131, - -1, 134, -1, 121, -1, 114, -1, 145, -1, 130, - -1, 119, -1, 116, -1, 124, -1, 122, -1, 123, - -1, 126, -1, 127, -1, 128, -1, 129, -1, 140, - -1, 11, -1, 92, 156, 83, 156, 93, -1, 92, - 156, 83, 46, 93, -1, 92, 47, 83, 156, 93, - -1, 92, 156, 93, -1, 43, -1, 43, 115, -1, - 43, 94, 117, 95, -1, 118, -1, 117, 91, 118, - -1, 117, 91, 85, -1, 86, 92, 164, 93, -1, - 25, 94, 120, 95, -1, 117, -1, 9, 67, -1, - 9, 67, 94, 150, 95, -1, 51, 37, -1, 52, - 67, 125, -1, 49, -1, -1, 66, 115, -1, 64, - 94, 147, 95, -1, 64, 94, 95, -1, 64, 125, - 53, 112, -1, 65, 94, 147, 95, -1, 65, 94, - 95, -1, 65, 53, 112, -1, 14, 94, 147, 95, - -1, 132, -1, 133, -1, 86, -1, 34, -1, 77, - -1, 112, 135, -1, 92, 136, 93, -1, 137, -1, - 138, -1, 139, -1, 19, 112, -1, 23, 12, 156, - -1, 19, 112, 23, 12, 156, -1, 18, 12, 94, - 95, -1, 141, 143, 112, -1, 96, 142, 89, 97, - -1, -1, 76, -1, 6, -1, 60, -1, -1, 27, - -1, 38, -1, 86, 112, 84, 156, -1, 146, -1, - 33, -1, 73, -1, 78, -1, 61, -1, 81, -1, - 36, -1, 10, -1, 79, -1, 149, -1, 147, 91, - 149, -1, 147, 91, 85, -1, 86, 112, -1, 148, - -1, 148, 54, -1, 148, 20, 156, -1, 151, -1, - 150, 91, 151, -1, 86, 92, 89, 93, -1, 153, - -1, -1, 94, 154, 95, -1, -1, 155, 154, -1, - 86, 92, 89, 93, -1, 86, -1, 89, -1, 157, - -1, 158, -1, 162, -1, 161, -1, 163, -1, 166, - -1, 165, -1, 159, -1, 160, -1, 86, -1, 88, - -1, 71, -1, 31, -1, 164, -1, 89, -1, 49, - -1, 153, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 235, 235, 242, 243, 245, 247, 250, 252, 255, - 256, 259, 260, 263, 264, 267, 268, 271, 283, 289, - 290, 293, 294, 297, 298, 301, 307, 315, 325, 326, - 327, 330, 331, 332, 333, 334, 335, 336, 337, 338, - 339, 340, 341, 342, 343, 346, 353, 363, 371, 379, - 390, 395, 401, 409, 415, 420, 424, 437, 445, 448, - 455, 463, 469, 478, 486, 487, 492, 498, 506, 515, - 521, 529, 537, 544, 545, 548, 559, 564, 571, 587, - 593, 596, 597, 600, 606, 614, 624, 630, 643, 652, - 655, 659, 663, 670, 673, 677, 684, 695, 698, 703, - 708, 713, 718, 723, 728, 733, 741, 747, 752, 763, - 774, 780, 786, 794, 800, 807, 820, 821, 824, 831, - 834, 845, 849, 860, 866, 867, 870, 871, 872, 873, - 874, 877, 880, 883, 894, 902, 908, 916, 924, 927, - 932 -}; -#endif - -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "kw_ABSENT", "kw_ABSTRACT_SYNTAX", - "kw_ALL", "kw_APPLICATION", "kw_AUTOMATIC", "kw_BEGIN", "kw_BIT", - "kw_BMPString", "kw_BOOLEAN", "kw_BY", "kw_CHARACTER", "kw_CHOICE", - "kw_CLASS", "kw_COMPONENT", "kw_COMPONENTS", "kw_CONSTRAINED", - "kw_CONTAINING", "kw_DEFAULT", "kw_DEFINITIONS", "kw_EMBEDDED", - "kw_ENCODED", "kw_END", "kw_ENUMERATED", "kw_EXCEPT", "kw_EXPLICIT", - "kw_EXPORTS", "kw_EXTENSIBILITY", "kw_EXTERNAL", "kw_FALSE", "kw_FROM", - "kw_GeneralString", "kw_GeneralizedTime", "kw_GraphicString", - "kw_IA5String", "kw_IDENTIFIER", "kw_IMPLICIT", "kw_IMPLIED", - "kw_IMPORTS", "kw_INCLUDES", "kw_INSTANCE", "kw_INTEGER", - "kw_INTERSECTION", "kw_ISO646String", "kw_MAX", "kw_MIN", - "kw_MINUS_INFINITY", "kw_NULL", "kw_NumericString", "kw_OBJECT", - "kw_OCTET", "kw_OF", "kw_OPTIONAL", "kw_ObjectDescriptor", "kw_PATTERN", - "kw_PDV", "kw_PLUS_INFINITY", "kw_PRESENT", "kw_PRIVATE", - "kw_PrintableString", "kw_REAL", "kw_RELATIVE_OID", "kw_SEQUENCE", - "kw_SET", "kw_SIZE", "kw_STRING", "kw_SYNTAX", "kw_T61String", "kw_TAGS", - "kw_TRUE", "kw_TYPE_IDENTIFIER", "kw_TeletexString", "kw_UNION", - "kw_UNIQUE", "kw_UNIVERSAL", "kw_UTCTime", "kw_UTF8String", - "kw_UniversalString", "kw_VideotexString", "kw_VisibleString", "kw_WITH", - "RANGE", "EEQUAL", "ELLIPSIS", "IDENTIFIER", "referencename", "STRING", - "NUMBER", "';'", "','", "'('", "')'", "'{'", "'}'", "'['", "']'", - "$accept", "ModuleDefinition", "TagDefault", "ExtensionDefault", - "ModuleBody", "Imports", "SymbolsImported", "SymbolsFromModuleList", - "SymbolsFromModule", "Exports", "AssignmentList", "Assignment", - "referencenames", "TypeAssignment", "Type", "BuiltinType", "BooleanType", - "range", "IntegerType", "NamedNumberList", "NamedNumber", - "EnumeratedType", "Enumerations", "BitStringType", - "ObjectIdentifierType", "OctetStringType", "NullType", "size", - "SequenceType", "SequenceOfType", "SetType", "SetOfType", "ChoiceType", - "ReferencedType", "DefinedType", "UsefulType", "ConstrainedType", - "Constraint", "ConstraintSpec", "GeneralConstraint", - "ContentsConstraint", "UserDefinedConstraint", "TaggedType", "Tag", - "Class", "tagenv", "ValueAssignment", "CharacterStringType", - "RestrictedCharactedStringType", "ComponentTypeList", "NamedType", - "ComponentType", "NamedBitList", "NamedBit", "objid_opt", "objid", - "objid_list", "objid_element", "Value", "BuiltinValue", - "ReferencedValue", "DefinedValue", "Valuereference", - "CharacterStringValue", "BooleanValue", "IntegerValue", "SignedNumber", - "NullValue", "ObjectIdentifierValue", 0 -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 59, 44, 40, 41, 123, 125, 91, 93 -}; -# endif - -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 98, 99, 100, 100, 100, 100, 101, 101, 102, - 102, 103, 103, 104, 104, 105, 105, 106, 107, 107, - 107, 108, 108, 109, 109, 110, 110, 111, 112, 112, - 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 114, 115, 115, 115, 115, - 116, 116, 116, 117, 117, 117, 118, 119, 120, 121, - 121, 122, 123, 124, 125, 125, 126, 126, 127, 128, - 128, 129, 130, 131, 131, 132, 133, 133, 134, 135, - 136, 137, 137, 138, 138, 138, 139, 140, 141, 142, - 142, 142, 142, 143, 143, 143, 144, 145, 146, 146, - 146, 146, 146, 146, 146, 146, 147, 147, 147, 148, - 149, 149, 149, 150, 150, 151, 152, 152, 153, 154, - 154, 155, 155, 155, 156, 156, 157, 157, 157, 157, - 157, 158, 159, 160, 161, 162, 162, 163, 164, 165, - 166 -}; - -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 9, 2, 2, 2, 0, 2, 0, 3, - 0, 3, 0, 1, 0, 1, 2, 4, 3, 2, - 0, 1, 2, 1, 1, 3, 1, 3, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 5, 5, 5, 3, - 1, 2, 4, 1, 3, 3, 4, 4, 1, 2, - 5, 2, 3, 1, 0, 2, 4, 3, 4, 4, - 3, 3, 4, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 1, 2, 3, 5, 4, 3, 4, 0, - 1, 1, 1, 0, 1, 1, 4, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 3, 2, - 1, 2, 3, 1, 3, 4, 1, 0, 3, 0, - 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1 -}; - -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const yytype_uint8 yydefact[] = -{ - 0, 117, 0, 119, 0, 116, 1, 122, 123, 0, - 119, 6, 0, 118, 120, 0, 0, 0, 8, 0, - 5, 3, 4, 0, 0, 121, 7, 0, 20, 0, - 0, 12, 19, 26, 0, 2, 14, 0, 0, 18, - 0, 13, 15, 0, 0, 9, 21, 23, 24, 25, - 11, 16, 0, 0, 104, 45, 0, 0, 98, 76, - 103, 50, 63, 0, 0, 101, 64, 0, 99, 77, - 100, 105, 102, 0, 75, 89, 0, 28, 32, 36, - 35, 31, 38, 39, 37, 40, 41, 42, 43, 34, - 29, 73, 74, 30, 44, 93, 33, 97, 22, 117, - 59, 0, 0, 0, 0, 51, 61, 64, 0, 0, - 0, 0, 0, 27, 91, 92, 90, 0, 0, 0, - 78, 94, 95, 0, 17, 0, 0, 0, 110, 106, - 0, 58, 53, 0, 136, 0, 139, 135, 133, 134, - 138, 140, 0, 124, 125, 131, 132, 127, 126, 128, - 137, 130, 129, 0, 62, 65, 67, 0, 0, 71, - 70, 0, 0, 96, 0, 0, 0, 0, 80, 81, - 82, 87, 0, 0, 113, 109, 0, 72, 0, 111, - 0, 0, 57, 0, 0, 49, 52, 66, 68, 69, - 88, 0, 83, 0, 79, 0, 0, 60, 108, 107, - 112, 0, 55, 54, 0, 0, 0, 0, 0, 84, - 0, 114, 56, 48, 47, 46, 86, 0, 115, 85 -}; - -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 2, 18, 24, 30, 37, 40, 41, 42, 31, - 45, 46, 43, 47, 76, 77, 78, 105, 79, 131, - 132, 80, 133, 81, 82, 83, 84, 110, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 120, 167, 168, - 169, 170, 94, 95, 117, 123, 48, 96, 97, 127, - 128, 129, 173, 174, 4, 141, 9, 10, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152 -}; - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -119 -static const yytype_int16 yypact[] = -{ - -43, -56, 47, -65, 29, -119, -119, -31, -119, -25, - -65, 4, -1, -119, -119, 17, 20, 26, 50, 13, - -119, -119, -119, 63, 24, -119, -119, 104, 8, -2, - 89, 74, -119, 33, 25, -119, 34, 39, 34, -119, - 37, 34, -119, 98, 58, -119, 39, -119, -119, -119, - -119, -119, 52, 66, -119, -119, 51, 53, -119, -119, - -119, -79, -119, 109, 81, -119, -60, -48, -119, -119, - -119, -119, -119, 107, -119, 2, -74, -119, -119, -119, - -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, - -119, -119, -119, -119, -119, -18, -119, -119, -119, -56, - 55, 65, 67, -12, 67, -119, -119, 86, 68, -70, - 102, 107, -69, 69, -119, -119, -119, 73, 40, 10, - -119, -119, -119, 107, -119, 71, 107, -47, -13, -119, - 72, 75, -119, 70, -119, 80, -119, -119, -119, -119, - -119, -119, -71, -119, -119, -119, -119, -119, -119, -119, - -119, -119, -119, -46, -119, -119, -119, -39, 107, 69, - -119, -38, 76, -119, 155, 107, 157, 77, -119, -119, - -119, 69, 82, -10, -119, 69, -22, -119, 40, -119, - 87, 19, -119, 40, 9, -119, -119, -119, 69, -119, - -119, 83, -19, 40, -119, 90, 71, -119, -119, -119, - -119, 85, -119, -119, 88, 94, 96, 95, 163, -119, - 99, -119, -119, -119, -119, -119, -119, 40, -119, -119 -}; - -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -119, -119, -119, -119, -119, -119, -119, -119, 141, -119, - 137, -119, -15, -119, -72, -119, -119, 91, -119, 92, - 14, -119, -119, -119, -119, -119, -119, 84, -119, -119, - -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, - -119, -119, -119, -119, -119, -119, -119, -119, -119, -82, - -119, 18, -119, 5, 101, 1, 187, -119, -118, -119, - -119, -119, -119, -119, -119, -119, 22, -119, -119 -}; - -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -11 -static const yytype_int16 yytable[] = -{ - 163, 113, 5, 32, 208, 111, 108, 178, 114, 121, - 118, 15, 184, 103, 34, 104, 126, 126, 119, 134, - 122, 7, 185, 49, 8, 156, 160, 157, 164, 165, - 161, 16, -10, 166, 109, 135, 29, 136, 3, 159, - 134, 179, 17, 1, 176, 181, 112, 6, 177, 186, - 11, 171, 176, 176, 175, 205, 187, 189, 136, 137, - 200, 12, 115, 198, 126, 204, 206, 53, 54, 55, - 13, 134, 56, 119, 138, 209, 139, 140, 116, 23, - 137, 196, 3, 57, 33, 197, 188, 20, 19, 136, - 21, 58, 59, 192, 60, 138, 22, 139, 140, 219, - 5, 61, 26, 3, 202, 130, 25, 62, 27, 63, - 64, 137, 28, 35, 36, 39, 53, 54, 55, 65, - 33, 56, 66, 67, 38, 44, 138, 50, 139, 140, - 52, 68, 57, 100, 3, 69, 70, 71, 99, 72, - 58, 59, 73, 60, 74, 101, 106, 102, 107, 125, - 61, 126, 108, 130, 75, 158, 62, 172, 63, 64, - 103, 119, 162, 183, 180, 182, 181, 191, 65, 193, - 194, 66, 67, 190, 195, 217, 140, 207, 212, 210, - 68, 213, 51, 98, 69, 70, 71, 214, 72, 215, - 216, 154, 218, 74, 199, 203, 153, 14, 0, 155, - 124, 211, 201, 75 -}; - -static const yytype_int16 yycheck[] = -{ - 118, 73, 1, 5, 23, 53, 66, 20, 6, 27, - 84, 7, 83, 92, 29, 94, 86, 86, 92, 31, - 38, 86, 93, 38, 89, 95, 95, 109, 18, 19, - 112, 27, 24, 23, 94, 47, 28, 49, 94, 111, - 31, 54, 38, 86, 91, 91, 94, 0, 95, 95, - 21, 123, 91, 91, 126, 46, 95, 95, 49, 71, - 178, 92, 60, 85, 86, 183, 184, 9, 10, 11, - 95, 31, 14, 92, 86, 193, 88, 89, 76, 29, - 71, 91, 94, 25, 86, 95, 158, 70, 89, 49, - 70, 33, 34, 165, 36, 86, 70, 88, 89, 217, - 99, 43, 39, 94, 85, 86, 93, 49, 84, 51, - 52, 71, 8, 24, 40, 90, 9, 10, 11, 61, - 86, 14, 64, 65, 91, 86, 86, 90, 88, 89, - 32, 73, 25, 67, 94, 77, 78, 79, 86, 81, - 33, 34, 84, 36, 86, 94, 37, 94, 67, 94, - 43, 86, 66, 86, 96, 53, 49, 86, 51, 52, - 92, 92, 89, 83, 92, 95, 91, 12, 61, 12, - 93, 64, 65, 97, 92, 12, 89, 94, 93, 89, - 73, 93, 41, 46, 77, 78, 79, 93, 81, 93, - 95, 107, 93, 86, 176, 181, 104, 10, -1, 108, - 99, 196, 180, 96 -}; - -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint8 yystos[] = -{ - 0, 86, 99, 94, 152, 153, 0, 86, 89, 154, - 155, 21, 92, 95, 154, 7, 27, 38, 100, 89, - 70, 70, 70, 29, 101, 93, 39, 84, 8, 28, - 102, 107, 5, 86, 110, 24, 40, 103, 91, 90, - 104, 105, 106, 110, 86, 108, 109, 111, 144, 110, - 90, 106, 32, 9, 10, 11, 14, 25, 33, 34, - 36, 43, 49, 51, 52, 61, 64, 65, 73, 77, - 78, 79, 81, 84, 86, 96, 112, 113, 114, 116, - 119, 121, 122, 123, 124, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 140, 141, 145, 146, 108, 86, - 67, 94, 94, 92, 94, 115, 37, 67, 66, 94, - 125, 53, 94, 112, 6, 60, 76, 142, 84, 92, - 135, 27, 38, 143, 152, 94, 86, 147, 148, 149, - 86, 117, 118, 120, 31, 47, 49, 71, 86, 88, - 89, 153, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 117, 125, 115, 95, 147, 53, 112, - 95, 147, 89, 156, 18, 19, 23, 136, 137, 138, - 139, 112, 86, 150, 151, 112, 91, 95, 20, 54, - 92, 91, 95, 83, 83, 93, 95, 95, 112, 95, - 97, 12, 112, 12, 93, 92, 91, 95, 85, 149, - 156, 164, 85, 118, 156, 46, 156, 94, 23, 156, - 89, 151, 93, 93, 93, 93, 95, 12, 93, 156 -}; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ - -#define YYFAIL goto yyerrlab - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (YYID (0)) - - -#define YYTERROR 1 -#define YYERRCODE 256 - - -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif -#endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (YYLEX_PARAM) -#else -# define YYLEX yylex () -#endif - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (YYID (0)) - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (YYID (0)) - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); -# endif - switch (yytype) - { - default: - break; - } -} - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - - yy_symbol_value_print (yyoutput, yytype, yyvaluep); - YYFPRINTF (yyoutput, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -#else -static void -yy_stack_print (yybottom, yytop) - yytype_int16 *yybottom; - yytype_int16 *yytop; -#endif -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule) -#else -static void -yy_reduce_print (yyvsp, yyrule) - YYSTYPE *yyvsp; - int yyrule; -#endif -{ - int yynrhs = yyr2[yyrule]; - int yyi; - unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], - &(yyvsp[(yyi + 1) - (yynrhs)]) - ); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyvsp, Rule); \ -} while (YYID (0)) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static YYSIZE_T -yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static char * -yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) -{ - int yyn = yypact[yystate]; - - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else - { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; - } -} -#endif /* YYERROR_VERBOSE */ - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -#else -static void -yydestruct (yymsg, yytype, yyvaluep) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; -#endif -{ - YYUSE (yyvaluep); - - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - switch (yytype) - { - - default: - break; - } -} - -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - -/* The lookahead symbol. */ -int yychar; - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; - -/* Number of syntax errors so far. */ -int yynerrs; - - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ - -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void) -#else -int -yyparse () - -#endif -#endif -{ - - - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - `yyss': related to states. - `yyvs': related to semantic values. - - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; - - int yyn; - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; - yystacksize = YYINITDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyss + yystacksize - 1 <= yyssp) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - - yystate = yyn; - *++yyvsp = yylval; - - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: - -/* Line 1455 of yacc.c */ -#line 237 "heimdal/lib/asn1/asn1parse.y" - { - checkundefined(); - } - break; - - case 4: - -/* Line 1455 of yacc.c */ -#line 244 "heimdal/lib/asn1/asn1parse.y" - { lex_err_message("implicit tagging is not supported"); } - break; - - case 5: - -/* Line 1455 of yacc.c */ -#line 246 "heimdal/lib/asn1/asn1parse.y" - { lex_err_message("automatic tagging is not supported"); } - break; - - case 7: - -/* Line 1455 of yacc.c */ -#line 251 "heimdal/lib/asn1/asn1parse.y" - { lex_err_message("no extensibility options supported"); } - break; - - case 17: - -/* Line 1455 of yacc.c */ -#line 272 "heimdal/lib/asn1/asn1parse.y" - { - struct string_list *sl; - for(sl = (yyvsp[(1) - (4)].sl); sl != NULL; sl = sl->next) { - Symbol *s = addsym(sl->string); - s->stype = Stype; - gen_template_import(s); - } - add_import((yyvsp[(3) - (4)].name)); - } - break; - - case 18: - -/* Line 1455 of yacc.c */ -#line 284 "heimdal/lib/asn1/asn1parse.y" - { - struct string_list *sl; - for(sl = (yyvsp[(2) - (3)].sl); sl != NULL; sl = sl->next) - add_export(sl->string); - } - break; - - case 25: - -/* Line 1455 of yacc.c */ -#line 302 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.sl) = emalloc(sizeof(*(yyval.sl))); - (yyval.sl)->string = (yyvsp[(1) - (3)].name); - (yyval.sl)->next = (yyvsp[(3) - (3)].sl); - } - break; - - case 26: - -/* Line 1455 of yacc.c */ -#line 308 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.sl) = emalloc(sizeof(*(yyval.sl))); - (yyval.sl)->string = (yyvsp[(1) - (1)].name); - (yyval.sl)->next = NULL; - } - break; - - case 27: - -/* Line 1455 of yacc.c */ -#line 316 "heimdal/lib/asn1/asn1parse.y" - { - Symbol *s = addsym ((yyvsp[(1) - (3)].name)); - s->stype = Stype; - s->type = (yyvsp[(3) - (3)].type); - fix_labels(s); - generate_type (s); - } - break; - - case 45: - -/* Line 1455 of yacc.c */ -#line 347 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Boolean, - TE_EXPLICIT, new_type(TBoolean)); - } - break; - - case 46: - -/* Line 1455 of yacc.c */ -#line 354 "heimdal/lib/asn1/asn1parse.y" - { - if((yyvsp[(2) - (5)].value)->type != integervalue) - lex_err_message("Non-integer used in first part of range"); - if((yyvsp[(2) - (5)].value)->type != integervalue) - lex_err_message("Non-integer in second part of range"); - (yyval.range) = ecalloc(1, sizeof(*(yyval.range))); - (yyval.range)->min = (yyvsp[(2) - (5)].value)->u.integervalue; - (yyval.range)->max = (yyvsp[(4) - (5)].value)->u.integervalue; - } - break; - - case 47: - -/* Line 1455 of yacc.c */ -#line 364 "heimdal/lib/asn1/asn1parse.y" - { - if((yyvsp[(2) - (5)].value)->type != integervalue) - lex_err_message("Non-integer in first part of range"); - (yyval.range) = ecalloc(1, sizeof(*(yyval.range))); - (yyval.range)->min = (yyvsp[(2) - (5)].value)->u.integervalue; - (yyval.range)->max = (yyvsp[(2) - (5)].value)->u.integervalue - 1; - } - break; - - case 48: - -/* Line 1455 of yacc.c */ -#line 372 "heimdal/lib/asn1/asn1parse.y" - { - if((yyvsp[(4) - (5)].value)->type != integervalue) - lex_err_message("Non-integer in second part of range"); - (yyval.range) = ecalloc(1, sizeof(*(yyval.range))); - (yyval.range)->min = (yyvsp[(4) - (5)].value)->u.integervalue + 2; - (yyval.range)->max = (yyvsp[(4) - (5)].value)->u.integervalue; - } - break; - - case 49: - -/* Line 1455 of yacc.c */ -#line 380 "heimdal/lib/asn1/asn1parse.y" - { - if((yyvsp[(2) - (3)].value)->type != integervalue) - lex_err_message("Non-integer used in limit"); - (yyval.range) = ecalloc(1, sizeof(*(yyval.range))); - (yyval.range)->min = (yyvsp[(2) - (3)].value)->u.integervalue; - (yyval.range)->max = (yyvsp[(2) - (3)].value)->u.integervalue; - } - break; - - case 50: - -/* Line 1455 of yacc.c */ -#line 391 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Integer, - TE_EXPLICIT, new_type(TInteger)); - } - break; - - case 51: - -/* Line 1455 of yacc.c */ -#line 396 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TInteger); - (yyval.type)->range = (yyvsp[(2) - (2)].range); - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, (yyval.type)); - } - break; - - case 52: - -/* Line 1455 of yacc.c */ -#line 402 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TInteger); - (yyval.type)->members = (yyvsp[(3) - (4)].members); - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, (yyval.type)); - } - break; - - case 53: - -/* Line 1455 of yacc.c */ -#line 410 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.members) = emalloc(sizeof(*(yyval.members))); - ASN1_TAILQ_INIT((yyval.members)); - ASN1_TAILQ_INSERT_HEAD((yyval.members), (yyvsp[(1) - (1)].member), members); - } - break; - - case 54: - -/* Line 1455 of yacc.c */ -#line 416 "heimdal/lib/asn1/asn1parse.y" - { - ASN1_TAILQ_INSERT_TAIL((yyvsp[(1) - (3)].members), (yyvsp[(3) - (3)].member), members); - (yyval.members) = (yyvsp[(1) - (3)].members); - } - break; - - case 55: - -/* Line 1455 of yacc.c */ -#line 421 "heimdal/lib/asn1/asn1parse.y" - { (yyval.members) = (yyvsp[(1) - (3)].members); } - break; - - case 56: - -/* Line 1455 of yacc.c */ -#line 425 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.member) = emalloc(sizeof(*(yyval.member))); - (yyval.member)->name = (yyvsp[(1) - (4)].name); - (yyval.member)->gen_name = estrdup((yyvsp[(1) - (4)].name)); - output_name ((yyval.member)->gen_name); - (yyval.member)->val = (yyvsp[(3) - (4)].constant); - (yyval.member)->optional = 0; - (yyval.member)->ellipsis = 0; - (yyval.member)->type = NULL; - } - break; - - case 57: - -/* Line 1455 of yacc.c */ -#line 438 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TInteger); - (yyval.type)->members = (yyvsp[(3) - (4)].members); - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Enumerated, TE_EXPLICIT, (yyval.type)); - } - break; - - case 59: - -/* Line 1455 of yacc.c */ -#line 449 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TBitString); - (yyval.type)->members = emalloc(sizeof(*(yyval.type)->members)); - ASN1_TAILQ_INIT((yyval.type)->members); - (yyval.type) = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, (yyval.type)); - } - break; - - case 60: - -/* Line 1455 of yacc.c */ -#line 456 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TBitString); - (yyval.type)->members = (yyvsp[(4) - (5)].members); - (yyval.type) = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, (yyval.type)); - } - break; - - case 61: - -/* Line 1455 of yacc.c */ -#line 464 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_OID, - TE_EXPLICIT, new_type(TOID)); - } - break; - - case 62: - -/* Line 1455 of yacc.c */ -#line 470 "heimdal/lib/asn1/asn1parse.y" - { - Type *t = new_type(TOctetString); - t->range = (yyvsp[(3) - (3)].range); - (yyval.type) = new_tag(ASN1_C_UNIV, UT_OctetString, - TE_EXPLICIT, t); - } - break; - - case 63: - -/* Line 1455 of yacc.c */ -#line 479 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Null, - TE_EXPLICIT, new_type(TNull)); - } - break; - - case 64: - -/* Line 1455 of yacc.c */ -#line 486 "heimdal/lib/asn1/asn1parse.y" - { (yyval.range) = NULL; } - break; - - case 65: - -/* Line 1455 of yacc.c */ -#line 488 "heimdal/lib/asn1/asn1parse.y" - { (yyval.range) = (yyvsp[(2) - (2)].range); } - break; - - case 66: - -/* Line 1455 of yacc.c */ -#line 493 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TSequence); - (yyval.type)->members = (yyvsp[(3) - (4)].members); - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, (yyval.type)); - } - break; - - case 67: - -/* Line 1455 of yacc.c */ -#line 499 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TSequence); - (yyval.type)->members = NULL; - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, (yyval.type)); - } - break; - - case 68: - -/* Line 1455 of yacc.c */ -#line 507 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TSequenceOf); - (yyval.type)->range = (yyvsp[(2) - (4)].range); - (yyval.type)->subtype = (yyvsp[(4) - (4)].type); - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, (yyval.type)); - } - break; - - case 69: - -/* Line 1455 of yacc.c */ -#line 516 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TSet); - (yyval.type)->members = (yyvsp[(3) - (4)].members); - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, (yyval.type)); - } - break; - - case 70: - -/* Line 1455 of yacc.c */ -#line 522 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TSet); - (yyval.type)->members = NULL; - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, (yyval.type)); - } - break; - - case 71: - -/* Line 1455 of yacc.c */ -#line 530 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TSetOf); - (yyval.type)->subtype = (yyvsp[(3) - (3)].type); - (yyval.type) = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, (yyval.type)); - } - break; - - case 72: - -/* Line 1455 of yacc.c */ -#line 538 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TChoice); - (yyval.type)->members = (yyvsp[(3) - (4)].members); - } - break; - - case 75: - -/* Line 1455 of yacc.c */ -#line 549 "heimdal/lib/asn1/asn1parse.y" - { - Symbol *s = addsym((yyvsp[(1) - (1)].name)); - (yyval.type) = new_type(TType); - if(s->stype != Stype && s->stype != SUndefined) - lex_err_message ("%s is not a type\n", (yyvsp[(1) - (1)].name)); - else - (yyval.type)->symbol = s; - } - break; - - case 76: - -/* Line 1455 of yacc.c */ -#line 560 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_GeneralizedTime, - TE_EXPLICIT, new_type(TGeneralizedTime)); - } - break; - - case 77: - -/* Line 1455 of yacc.c */ -#line 565 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_UTCTime, - TE_EXPLICIT, new_type(TUTCTime)); - } - break; - - case 78: - -/* Line 1455 of yacc.c */ -#line 572 "heimdal/lib/asn1/asn1parse.y" - { - /* if (Constraint.type == contentConstrant) { - assert(Constraint.u.constraint.type == octetstring|bitstring-w/o-NamedBitList); // remember to check type reference too - if (Constraint.u.constraint.type) { - assert((Constraint.u.constraint.type.length % 8) == 0); - } - } - if (Constraint.u.constraint.encoding) { - type == der-oid|ber-oid - } - */ - } - break; - - case 79: - -/* Line 1455 of yacc.c */ -#line 588 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.constraint_spec) = (yyvsp[(2) - (3)].constraint_spec); - } - break; - - case 83: - -/* Line 1455 of yacc.c */ -#line 601 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.constraint_spec) = new_constraint_spec(CT_CONTENTS); - (yyval.constraint_spec)->u.content.type = (yyvsp[(2) - (2)].type); - (yyval.constraint_spec)->u.content.encoding = NULL; - } - break; - - case 84: - -/* Line 1455 of yacc.c */ -#line 607 "heimdal/lib/asn1/asn1parse.y" - { - if ((yyvsp[(3) - (3)].value)->type != objectidentifiervalue) - lex_err_message("Non-OID used in ENCODED BY constraint"); - (yyval.constraint_spec) = new_constraint_spec(CT_CONTENTS); - (yyval.constraint_spec)->u.content.type = NULL; - (yyval.constraint_spec)->u.content.encoding = (yyvsp[(3) - (3)].value); - } - break; - - case 85: - -/* Line 1455 of yacc.c */ -#line 615 "heimdal/lib/asn1/asn1parse.y" - { - if ((yyvsp[(5) - (5)].value)->type != objectidentifiervalue) - lex_err_message("Non-OID used in ENCODED BY constraint"); - (yyval.constraint_spec) = new_constraint_spec(CT_CONTENTS); - (yyval.constraint_spec)->u.content.type = (yyvsp[(2) - (5)].type); - (yyval.constraint_spec)->u.content.encoding = (yyvsp[(5) - (5)].value); - } - break; - - case 86: - -/* Line 1455 of yacc.c */ -#line 625 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.constraint_spec) = new_constraint_spec(CT_USER); - } - break; - - case 87: - -/* Line 1455 of yacc.c */ -#line 631 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_type(TTag); - (yyval.type)->tag = (yyvsp[(1) - (3)].tag); - (yyval.type)->tag.tagenv = (yyvsp[(2) - (3)].constant); - if((yyvsp[(3) - (3)].type)->type == TTag && (yyvsp[(2) - (3)].constant) == TE_IMPLICIT) { - (yyval.type)->subtype = (yyvsp[(3) - (3)].type)->subtype; - free((yyvsp[(3) - (3)].type)); - } else - (yyval.type)->subtype = (yyvsp[(3) - (3)].type); - } - break; - - case 88: - -/* Line 1455 of yacc.c */ -#line 644 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.tag).tagclass = (yyvsp[(2) - (4)].constant); - (yyval.tag).tagvalue = (yyvsp[(3) - (4)].constant); - (yyval.tag).tagenv = TE_EXPLICIT; - } - break; - - case 89: - -/* Line 1455 of yacc.c */ -#line 652 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.constant) = ASN1_C_CONTEXT; - } - break; - - case 90: - -/* Line 1455 of yacc.c */ -#line 656 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.constant) = ASN1_C_UNIV; - } - break; - - case 91: - -/* Line 1455 of yacc.c */ -#line 660 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.constant) = ASN1_C_APPL; - } - break; - - case 92: - -/* Line 1455 of yacc.c */ -#line 664 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.constant) = ASN1_C_PRIVATE; - } - break; - - case 93: - -/* Line 1455 of yacc.c */ -#line 670 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.constant) = TE_EXPLICIT; - } - break; - - case 94: - -/* Line 1455 of yacc.c */ -#line 674 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.constant) = TE_EXPLICIT; - } - break; - - case 95: - -/* Line 1455 of yacc.c */ -#line 678 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.constant) = TE_IMPLICIT; - } - break; - - case 96: - -/* Line 1455 of yacc.c */ -#line 685 "heimdal/lib/asn1/asn1parse.y" - { - Symbol *s; - s = addsym ((yyvsp[(1) - (4)].name)); - - s->stype = SValue; - s->value = (yyvsp[(4) - (4)].value); - generate_constant (s); - } - break; - - case 98: - -/* Line 1455 of yacc.c */ -#line 699 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_GeneralString, - TE_EXPLICIT, new_type(TGeneralString)); - } - break; - - case 99: - -/* Line 1455 of yacc.c */ -#line 704 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_TeletexString, - TE_EXPLICIT, new_type(TTeletexString)); - } - break; - - case 100: - -/* Line 1455 of yacc.c */ -#line 709 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_UTF8String, - TE_EXPLICIT, new_type(TUTF8String)); - } - break; - - case 101: - -/* Line 1455 of yacc.c */ -#line 714 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_PrintableString, - TE_EXPLICIT, new_type(TPrintableString)); - } - break; - - case 102: - -/* Line 1455 of yacc.c */ -#line 719 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_VisibleString, - TE_EXPLICIT, new_type(TVisibleString)); - } - break; - - case 103: - -/* Line 1455 of yacc.c */ -#line 724 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_IA5String, - TE_EXPLICIT, new_type(TIA5String)); - } - break; - - case 104: - -/* Line 1455 of yacc.c */ -#line 729 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_BMPString, - TE_EXPLICIT, new_type(TBMPString)); - } - break; - - case 105: - -/* Line 1455 of yacc.c */ -#line 734 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.type) = new_tag(ASN1_C_UNIV, UT_UniversalString, - TE_EXPLICIT, new_type(TUniversalString)); - } - break; - - case 106: - -/* Line 1455 of yacc.c */ -#line 742 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.members) = emalloc(sizeof(*(yyval.members))); - ASN1_TAILQ_INIT((yyval.members)); - ASN1_TAILQ_INSERT_HEAD((yyval.members), (yyvsp[(1) - (1)].member), members); - } - break; - - case 107: - -/* Line 1455 of yacc.c */ -#line 748 "heimdal/lib/asn1/asn1parse.y" - { - ASN1_TAILQ_INSERT_TAIL((yyvsp[(1) - (3)].members), (yyvsp[(3) - (3)].member), members); - (yyval.members) = (yyvsp[(1) - (3)].members); - } - break; - - case 108: - -/* Line 1455 of yacc.c */ -#line 753 "heimdal/lib/asn1/asn1parse.y" - { - struct member *m = ecalloc(1, sizeof(*m)); - m->name = estrdup("..."); - m->gen_name = estrdup("asn1_ellipsis"); - m->ellipsis = 1; - ASN1_TAILQ_INSERT_TAIL((yyvsp[(1) - (3)].members), m, members); - (yyval.members) = (yyvsp[(1) - (3)].members); - } - break; - - case 109: - -/* Line 1455 of yacc.c */ -#line 764 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.member) = emalloc(sizeof(*(yyval.member))); - (yyval.member)->name = (yyvsp[(1) - (2)].name); - (yyval.member)->gen_name = estrdup((yyvsp[(1) - (2)].name)); - output_name ((yyval.member)->gen_name); - (yyval.member)->type = (yyvsp[(2) - (2)].type); - (yyval.member)->ellipsis = 0; - } - break; - - case 110: - -/* Line 1455 of yacc.c */ -#line 775 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.member) = (yyvsp[(1) - (1)].member); - (yyval.member)->optional = 0; - (yyval.member)->defval = NULL; - } - break; - - case 111: - -/* Line 1455 of yacc.c */ -#line 781 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.member) = (yyvsp[(1) - (2)].member); - (yyval.member)->optional = 1; - (yyval.member)->defval = NULL; - } - break; - - case 112: - -/* Line 1455 of yacc.c */ -#line 787 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.member) = (yyvsp[(1) - (3)].member); - (yyval.member)->optional = 0; - (yyval.member)->defval = (yyvsp[(3) - (3)].value); - } - break; - - case 113: - -/* Line 1455 of yacc.c */ -#line 795 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.members) = emalloc(sizeof(*(yyval.members))); - ASN1_TAILQ_INIT((yyval.members)); - ASN1_TAILQ_INSERT_HEAD((yyval.members), (yyvsp[(1) - (1)].member), members); - } - break; - - case 114: - -/* Line 1455 of yacc.c */ -#line 801 "heimdal/lib/asn1/asn1parse.y" - { - ASN1_TAILQ_INSERT_TAIL((yyvsp[(1) - (3)].members), (yyvsp[(3) - (3)].member), members); - (yyval.members) = (yyvsp[(1) - (3)].members); - } - break; - - case 115: - -/* Line 1455 of yacc.c */ -#line 808 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.member) = emalloc(sizeof(*(yyval.member))); - (yyval.member)->name = (yyvsp[(1) - (4)].name); - (yyval.member)->gen_name = estrdup((yyvsp[(1) - (4)].name)); - output_name ((yyval.member)->gen_name); - (yyval.member)->val = (yyvsp[(3) - (4)].constant); - (yyval.member)->optional = 0; - (yyval.member)->ellipsis = 0; - (yyval.member)->type = NULL; - } - break; - - case 117: - -/* Line 1455 of yacc.c */ -#line 821 "heimdal/lib/asn1/asn1parse.y" - { (yyval.objid) = NULL; } - break; - - case 118: - -/* Line 1455 of yacc.c */ -#line 825 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.objid) = (yyvsp[(2) - (3)].objid); - } - break; - - case 119: - -/* Line 1455 of yacc.c */ -#line 831 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.objid) = NULL; - } - break; - - case 120: - -/* Line 1455 of yacc.c */ -#line 835 "heimdal/lib/asn1/asn1parse.y" - { - if ((yyvsp[(2) - (2)].objid)) { - (yyval.objid) = (yyvsp[(2) - (2)].objid); - add_oid_to_tail((yyvsp[(2) - (2)].objid), (yyvsp[(1) - (2)].objid)); - } else { - (yyval.objid) = (yyvsp[(1) - (2)].objid); - } - } - break; - - case 121: - -/* Line 1455 of yacc.c */ -#line 846 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.objid) = new_objid((yyvsp[(1) - (4)].name), (yyvsp[(3) - (4)].constant)); - } - break; - - case 122: - -/* Line 1455 of yacc.c */ -#line 850 "heimdal/lib/asn1/asn1parse.y" - { - Symbol *s = addsym((yyvsp[(1) - (1)].name)); - if(s->stype != SValue || - s->value->type != objectidentifiervalue) { - lex_err_message("%s is not an object identifier\n", - s->name); - exit(1); - } - (yyval.objid) = s->value->u.objectidentifiervalue; - } - break; - - case 123: - -/* Line 1455 of yacc.c */ -#line 861 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.objid) = new_objid(NULL, (yyvsp[(1) - (1)].constant)); - } - break; - - case 133: - -/* Line 1455 of yacc.c */ -#line 884 "heimdal/lib/asn1/asn1parse.y" - { - Symbol *s = addsym((yyvsp[(1) - (1)].name)); - if(s->stype != SValue) - lex_err_message ("%s is not a value\n", - s->name); - else - (yyval.value) = s->value; - } - break; - - case 134: - -/* Line 1455 of yacc.c */ -#line 895 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.value) = emalloc(sizeof(*(yyval.value))); - (yyval.value)->type = stringvalue; - (yyval.value)->u.stringvalue = (yyvsp[(1) - (1)].name); - } - break; - - case 135: - -/* Line 1455 of yacc.c */ -#line 903 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.value) = emalloc(sizeof(*(yyval.value))); - (yyval.value)->type = booleanvalue; - (yyval.value)->u.booleanvalue = 0; - } - break; - - case 136: - -/* Line 1455 of yacc.c */ -#line 909 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.value) = emalloc(sizeof(*(yyval.value))); - (yyval.value)->type = booleanvalue; - (yyval.value)->u.booleanvalue = 0; - } - break; - - case 137: - -/* Line 1455 of yacc.c */ -#line 917 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.value) = emalloc(sizeof(*(yyval.value))); - (yyval.value)->type = integervalue; - (yyval.value)->u.integervalue = (yyvsp[(1) - (1)].constant); - } - break; - - case 139: - -/* Line 1455 of yacc.c */ -#line 928 "heimdal/lib/asn1/asn1parse.y" - { - } - break; - - case 140: - -/* Line 1455 of yacc.c */ -#line 933 "heimdal/lib/asn1/asn1parse.y" - { - (yyval.value) = emalloc(sizeof(*(yyval.value))); - (yyval.value)->type = objectidentifiervalue; - (yyval.value)->u.objectidentifiervalue = (yyvsp[(1) - (1)].objid); - } - break; - - - -/* Line 1455 of yacc.c */ -#line 2736 "heimdal/lib/asn1/asn1parse.y" - default: break; - } - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; - - goto yynewstate; - - -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); -#else - { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (yymsg); - } - else - { - yyerror (YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } - } -#endif - } - - - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - /* Do not reclaim the symbols of the rule which action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - yystos[yystate], yyvsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - *++yyvsp = yylval; - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -#if !defined(yyoverflow) || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - -yyreturn: - if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - /* Do not reclaim the symbols of the rule which action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - /* Make sure YYID is used. */ - return YYID (yyresult); -} - - - -/* Line 1675 of yacc.c */ -#line 940 "heimdal/lib/asn1/asn1parse.y" - - -void -yyerror (const char *s) -{ - lex_err_message ("%s\n", s); -} - -static Type * -new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype) -{ - Type *t; - if(oldtype->type == TTag && oldtype->tag.tagenv == TE_IMPLICIT) { - t = oldtype; - oldtype = oldtype->subtype; /* XXX */ - } else - t = new_type (TTag); - - t->tag.tagclass = tagclass; - t->tag.tagvalue = tagvalue; - t->tag.tagenv = tagenv; - t->subtype = oldtype; - return t; -} - -static struct objid * -new_objid(const char *label, int value) -{ - struct objid *s; - s = emalloc(sizeof(*s)); - s->label = label; - s->value = value; - s->next = NULL; - return s; -} - -static void -add_oid_to_tail(struct objid *head, struct objid *tail) -{ - struct objid *o; - o = head; - while (o->next) - o = o->next; - o->next = tail; -} - -static Type * -new_type (Typetype tt) -{ - Type *t = ecalloc(1, sizeof(*t)); - t->type = tt; - return t; -} - -static struct constraint_spec * -new_constraint_spec(enum ctype ct) -{ - struct constraint_spec *c = ecalloc(1, sizeof(*c)); - c->ctype = ct; - return c; -} - -static void fix_labels2(Type *t, const char *prefix); -static void fix_labels1(struct memhead *members, const char *prefix) -{ - Member *m; - - if(members == NULL) - return; - ASN1_TAILQ_FOREACH(m, members, members) { - if (asprintf(&m->label, "%s_%s", prefix, m->gen_name) < 0) - errx(1, "malloc"); - if (m->label == NULL) - errx(1, "malloc"); - if(m->type != NULL) - fix_labels2(m->type, m->label); - } -} - -static void fix_labels2(Type *t, const char *prefix) -{ - for(; t; t = t->subtype) - fix_labels1(t->members, prefix); -} - -static void -fix_labels(Symbol *s) -{ - char *p = NULL; - if (asprintf(&p, "choice_%s", s->gen_name) < 0 || p == NULL) - errx(1, "malloc"); - fix_labels2(s->type, p); - free(p); -} - diff --git a/source4/heimdal/lib/asn1/asn1parse.h b/source4/heimdal/lib/asn1/asn1parse.h deleted file mode 100644 index dc3debb5c8..0000000000 --- a/source4/heimdal/lib/asn1/asn1parse.h +++ /dev/null @@ -1,255 +0,0 @@ - -/* A Bison parser, made by GNU Bison 2.4.1. */ - -/* Skeleton interface for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - kw_ABSENT = 258, - kw_ABSTRACT_SYNTAX = 259, - kw_ALL = 260, - kw_APPLICATION = 261, - kw_AUTOMATIC = 262, - kw_BEGIN = 263, - kw_BIT = 264, - kw_BMPString = 265, - kw_BOOLEAN = 266, - kw_BY = 267, - kw_CHARACTER = 268, - kw_CHOICE = 269, - kw_CLASS = 270, - kw_COMPONENT = 271, - kw_COMPONENTS = 272, - kw_CONSTRAINED = 273, - kw_CONTAINING = 274, - kw_DEFAULT = 275, - kw_DEFINITIONS = 276, - kw_EMBEDDED = 277, - kw_ENCODED = 278, - kw_END = 279, - kw_ENUMERATED = 280, - kw_EXCEPT = 281, - kw_EXPLICIT = 282, - kw_EXPORTS = 283, - kw_EXTENSIBILITY = 284, - kw_EXTERNAL = 285, - kw_FALSE = 286, - kw_FROM = 287, - kw_GeneralString = 288, - kw_GeneralizedTime = 289, - kw_GraphicString = 290, - kw_IA5String = 291, - kw_IDENTIFIER = 292, - kw_IMPLICIT = 293, - kw_IMPLIED = 294, - kw_IMPORTS = 295, - kw_INCLUDES = 296, - kw_INSTANCE = 297, - kw_INTEGER = 298, - kw_INTERSECTION = 299, - kw_ISO646String = 300, - kw_MAX = 301, - kw_MIN = 302, - kw_MINUS_INFINITY = 303, - kw_NULL = 304, - kw_NumericString = 305, - kw_OBJECT = 306, - kw_OCTET = 307, - kw_OF = 308, - kw_OPTIONAL = 309, - kw_ObjectDescriptor = 310, - kw_PATTERN = 311, - kw_PDV = 312, - kw_PLUS_INFINITY = 313, - kw_PRESENT = 314, - kw_PRIVATE = 315, - kw_PrintableString = 316, - kw_REAL = 317, - kw_RELATIVE_OID = 318, - kw_SEQUENCE = 319, - kw_SET = 320, - kw_SIZE = 321, - kw_STRING = 322, - kw_SYNTAX = 323, - kw_T61String = 324, - kw_TAGS = 325, - kw_TRUE = 326, - kw_TYPE_IDENTIFIER = 327, - kw_TeletexString = 328, - kw_UNION = 329, - kw_UNIQUE = 330, - kw_UNIVERSAL = 331, - kw_UTCTime = 332, - kw_UTF8String = 333, - kw_UniversalString = 334, - kw_VideotexString = 335, - kw_VisibleString = 336, - kw_WITH = 337, - RANGE = 338, - EEQUAL = 339, - ELLIPSIS = 340, - IDENTIFIER = 341, - referencename = 342, - STRING = 343, - NUMBER = 344 - }; -#endif -/* Tokens. */ -#define kw_ABSENT 258 -#define kw_ABSTRACT_SYNTAX 259 -#define kw_ALL 260 -#define kw_APPLICATION 261 -#define kw_AUTOMATIC 262 -#define kw_BEGIN 263 -#define kw_BIT 264 -#define kw_BMPString 265 -#define kw_BOOLEAN 266 -#define kw_BY 267 -#define kw_CHARACTER 268 -#define kw_CHOICE 269 -#define kw_CLASS 270 -#define kw_COMPONENT 271 -#define kw_COMPONENTS 272 -#define kw_CONSTRAINED 273 -#define kw_CONTAINING 274 -#define kw_DEFAULT 275 -#define kw_DEFINITIONS 276 -#define kw_EMBEDDED 277 -#define kw_ENCODED 278 -#define kw_END 279 -#define kw_ENUMERATED 280 -#define kw_EXCEPT 281 -#define kw_EXPLICIT 282 -#define kw_EXPORTS 283 -#define kw_EXTENSIBILITY 284 -#define kw_EXTERNAL 285 -#define kw_FALSE 286 -#define kw_FROM 287 -#define kw_GeneralString 288 -#define kw_GeneralizedTime 289 -#define kw_GraphicString 290 -#define kw_IA5String 291 -#define kw_IDENTIFIER 292 -#define kw_IMPLICIT 293 -#define kw_IMPLIED 294 -#define kw_IMPORTS 295 -#define kw_INCLUDES 296 -#define kw_INSTANCE 297 -#define kw_INTEGER 298 -#define kw_INTERSECTION 299 -#define kw_ISO646String 300 -#define kw_MAX 301 -#define kw_MIN 302 -#define kw_MINUS_INFINITY 303 -#define kw_NULL 304 -#define kw_NumericString 305 -#define kw_OBJECT 306 -#define kw_OCTET 307 -#define kw_OF 308 -#define kw_OPTIONAL 309 -#define kw_ObjectDescriptor 310 -#define kw_PATTERN 311 -#define kw_PDV 312 -#define kw_PLUS_INFINITY 313 -#define kw_PRESENT 314 -#define kw_PRIVATE 315 -#define kw_PrintableString 316 -#define kw_REAL 317 -#define kw_RELATIVE_OID 318 -#define kw_SEQUENCE 319 -#define kw_SET 320 -#define kw_SIZE 321 -#define kw_STRING 322 -#define kw_SYNTAX 323 -#define kw_T61String 324 -#define kw_TAGS 325 -#define kw_TRUE 326 -#define kw_TYPE_IDENTIFIER 327 -#define kw_TeletexString 328 -#define kw_UNION 329 -#define kw_UNIQUE 330 -#define kw_UNIVERSAL 331 -#define kw_UTCTime 332 -#define kw_UTF8String 333 -#define kw_UniversalString 334 -#define kw_VideotexString 335 -#define kw_VisibleString 336 -#define kw_WITH 337 -#define RANGE 338 -#define EEQUAL 339 -#define ELLIPSIS 340 -#define IDENTIFIER 341 -#define referencename 342 -#define STRING 343 -#define NUMBER 344 - - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE -{ - -/* Line 1676 of yacc.c */ -#line 67 "heimdal/lib/asn1/asn1parse.y" - - int constant; - struct value *value; - struct range *range; - char *name; - Type *type; - Member *member; - struct objid *objid; - char *defval; - struct string_list *sl; - struct tagtype tag; - struct memhead *members; - struct constraint_spec *constraint_spec; - - - -/* Line 1676 of yacc.c */ -#line 247 "heimdal/lib/asn1/asn1parse.y" -} YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - -extern YYSTYPE yylval; - - diff --git a/source4/heimdal/lib/asn1/asn1parse.y b/source4/heimdal/lib/asn1/asn1parse.y index 9ff9ad7707..dad7f67a20 100644 --- a/source4/heimdal/lib/asn1/asn1parse.y +++ b/source4/heimdal/lib/asn1/asn1parse.y @@ -241,14 +241,14 @@ ModuleDefinition: IDENTIFIER objid_opt kw_DEFINITIONS TagDefault ExtensionDefaul TagDefault : kw_EXPLICIT kw_TAGS | kw_IMPLICIT kw_TAGS - { lex_err_message("implicit tagging is not supported"); } + { lex_error_message("implicit tagging is not supported"); } | kw_AUTOMATIC kw_TAGS - { lex_err_message("automatic tagging is not supported"); } + { lex_error_message("automatic tagging is not supported"); } | /* empty */ ; ExtensionDefault: kw_EXTENSIBILITY kw_IMPLIED - { lex_err_message("no extensibility options supported"); } + { lex_error_message("no extensibility options supported"); } | /* empty */ ; @@ -353,9 +353,9 @@ BooleanType : kw_BOOLEAN range : '(' Value RANGE Value ')' { if($2->type != integervalue) - lex_err_message("Non-integer used in first part of range"); + lex_error_message("Non-integer used in first part of range"); if($2->type != integervalue) - lex_err_message("Non-integer in second part of range"); + lex_error_message("Non-integer in second part of range"); $$ = ecalloc(1, sizeof(*$$)); $$->min = $2->u.integervalue; $$->max = $4->u.integervalue; @@ -363,7 +363,7 @@ range : '(' Value RANGE Value ')' | '(' Value RANGE kw_MAX ')' { if($2->type != integervalue) - lex_err_message("Non-integer in first part of range"); + lex_error_message("Non-integer in first part of range"); $$ = ecalloc(1, sizeof(*$$)); $$->min = $2->u.integervalue; $$->max = $2->u.integervalue - 1; @@ -371,7 +371,7 @@ range : '(' Value RANGE Value ')' | '(' kw_MIN RANGE Value ')' { if($4->type != integervalue) - lex_err_message("Non-integer in second part of range"); + lex_error_message("Non-integer in second part of range"); $$ = ecalloc(1, sizeof(*$$)); $$->min = $4->u.integervalue + 2; $$->max = $4->u.integervalue; @@ -379,7 +379,7 @@ range : '(' Value RANGE Value ')' | '(' Value ')' { if($2->type != integervalue) - lex_err_message("Non-integer used in limit"); + lex_error_message("Non-integer used in limit"); $$ = ecalloc(1, sizeof(*$$)); $$->min = $2->u.integervalue; $$->max = $2->u.integervalue; @@ -550,7 +550,7 @@ DefinedType : IDENTIFIER Symbol *s = addsym($1); $$ = new_type(TType); if(s->stype != Stype && s->stype != SUndefined) - lex_err_message ("%s is not a type\n", $1); + lex_error_message ("%s is not a type\n", $1); else $$->symbol = s; } @@ -606,7 +606,7 @@ ContentsConstraint: kw_CONTAINING Type | kw_ENCODED kw_BY Value { if ($3->type != objectidentifiervalue) - lex_err_message("Non-OID used in ENCODED BY constraint"); + lex_error_message("Non-OID used in ENCODED BY constraint"); $$ = new_constraint_spec(CT_CONTENTS); $$->u.content.type = NULL; $$->u.content.encoding = $3; @@ -614,7 +614,7 @@ ContentsConstraint: kw_CONTAINING Type | kw_CONTAINING Type kw_ENCODED kw_BY Value { if ($5->type != objectidentifiervalue) - lex_err_message("Non-OID used in ENCODED BY constraint"); + lex_error_message("Non-OID used in ENCODED BY constraint"); $$ = new_constraint_spec(CT_CONTENTS); $$->u.content.type = $2; $$->u.content.encoding = $5; @@ -851,7 +851,7 @@ objid_element : IDENTIFIER '(' NUMBER ')' Symbol *s = addsym($1); if(s->stype != SValue || s->value->type != objectidentifiervalue) { - lex_err_message("%s is not an object identifier\n", + lex_error_message("%s is not an object identifier\n", s->name); exit(1); } @@ -884,7 +884,7 @@ Valuereference : IDENTIFIER { Symbol *s = addsym($1); if(s->stype != SValue) - lex_err_message ("%s is not a value\n", + lex_error_message ("%s is not a value\n", s->name); else $$ = s->value; @@ -942,7 +942,7 @@ ObjectIdentifierValue: objid void yyerror (const char *s) { - lex_err_message ("%s\n", s); + lex_error_message ("%s\n", s); } static Type * diff --git a/source4/heimdal/lib/asn1/gen_decode.c b/source4/heimdal/lib/asn1/gen_decode.c index 5a24339c42..002a471e96 100644 --- a/source4/heimdal/lib/asn1/gen_decode.c +++ b/source4/heimdal/lib/asn1/gen_decode.c @@ -143,10 +143,10 @@ find_tag (const Type *t, case TType: if ((t->symbol->stype == Stype && t->symbol->type == NULL) || t->symbol->stype == SUndefined) { - lex_err_message("%s is imported or still undefined, " - " can't generate tag checking data in CHOICE " - "without this information", - t->symbol->name); + lex_error_message("%s is imported or still undefined, " + " can't generate tag checking data in CHOICE " + "without this information", + t->symbol->name); exit(1); } find_tag(t->symbol->type, cl, ty, tag); diff --git a/source4/heimdal/lib/asn1/lex.h b/source4/heimdal/lib/asn1/lex.h index f203c98f1f..1ee5341789 100644 --- a/source4/heimdal/lib/asn1/lex.h +++ b/source4/heimdal/lib/asn1/lex.h @@ -35,7 +35,7 @@ #include -void lex_err_message (const char *, ...) +void lex_error_message (const char *, ...) __attribute__ ((format (printf, 1, 2))); extern int error_flag; diff --git a/source4/heimdal/lib/asn1/lex.l b/source4/heimdal/lib/asn1/lex.l index 3507d64b3a..dece096164 100644 --- a/source4/heimdal/lib/asn1/lex.l +++ b/source4/heimdal/lib/asn1/lex.l @@ -50,8 +50,6 @@ #include "lex.h" #include "gen_locl.h" -void lex_err_message (const char *format, ...); - static unsigned lineno = 1; #undef ECHO @@ -260,7 +258,7 @@ WITH { return kw_WITH; } yylval.constant = strtol((const char *)yytext, &e, 0); if(e == y) - lex_err_message("malformed constant (%s)", yytext); + lex_error_message("malformed constant (%s)", yytext); else return NUMBER; } @@ -272,7 +270,7 @@ WITH { return kw_WITH; } \n { ++lineno; } \.\.\. { return ELLIPSIS; } \.\. { return RANGE; } -. { lex_err_message("Ignoring char(%c)\n", *yytext); } +. { lex_error_message("Ignoring char(%c)\n", *yytext); } %% #ifndef yywrap /* XXX */ @@ -284,7 +282,7 @@ yywrap () #endif void -lex_err_message (const char *format, ...) +lex_error_message (const char *format, ...) { va_list args; @@ -298,5 +296,5 @@ lex_err_message (const char *format, ...) static void unterminated(const char *type, unsigned start_lineno) { - lex_err_message("unterminated %s, possibly started on line %d\n", type, start_lineno); + lex_error_message("unterminated %s, possibly started on line %d\n", type, start_lineno); } diff --git a/source4/heimdal/lib/asn1/symbol.c b/source4/heimdal/lib/asn1/symbol.c index 93d2cd4594..b05f68fa74 100644 --- a/source4/heimdal/lib/asn1/symbol.c +++ b/source4/heimdal/lib/asn1/symbol.c @@ -93,7 +93,7 @@ checkfunc(void *ptr, void *arg) { Symbol *s = ptr; if (s->stype == SUndefined) { - lex_err_message("%s is still undefined\n", s->name); + lex_error_message("%s is still undefined\n", s->name); *(int *) arg = 1; } return 0; diff --git a/source4/heimdal/lib/com_err/lex.h b/source4/heimdal/lib/com_err/lex.h index abfec922f0..76f3e2b2a5 100644 --- a/source4/heimdal/lib/com_err/lex.h +++ b/source4/heimdal/lib/com_err/lex.h @@ -33,7 +33,7 @@ /* $Id$ */ -void lex_err_message (const char *, ...) +void error_message (const char *, ...) __attribute__ ((format (printf, 1, 2))); int yylex(void); diff --git a/source4/heimdal/lib/com_err/lex.l b/source4/heimdal/lib/com_err/lex.l index f099c1e1bd..b68814b21c 100644 --- a/source4/heimdal/lib/com_err/lex.l +++ b/source4/heimdal/lib/com_err/lex.l @@ -94,7 +94,7 @@ getstring(void) continue; } if(c == '\n'){ - lex_err_message("unterminated string"); + error_message("unterminated string"); lineno++; break; } @@ -114,7 +114,7 @@ getstring(void) } void -lex_err_message (const char *format, ...) +error_message (const char *format, ...) { va_list args; diff --git a/source4/heimdal/lib/com_err/parse.y b/source4/heimdal/lib/com_err/parse.y index f1ae64d97e..d64681d902 100644 --- a/source4/heimdal/lib/com_err/parse.y +++ b/source4/heimdal/lib/com_err/parse.y @@ -167,5 +167,5 @@ name2number(const char *str) void yyerror (char *s) { - lex_err_message ("%s\n", s); + error_message ("%s\n", s); } diff --git a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c index 4538a5376e..53855ca045 100644 --- a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -768,22 +768,21 @@ repl_mutual /* There is no OID wrapping. */ indata.length = input_token->length; indata.data = input_token->value; - kret = krb5_rd_rep (context, - ctx->auth_context, - &indata, - &repl); - if (kret >= ASN1_BAD_TIMEFORMAT && kret <= ASN1_INDEF_EXTRA_DATA) { - ret = _gsskrb5_decapsulate (minor_status, - input_token, - &indata, - "\x03\x00", - GSS_KRB5_MECHANISM); + kret = krb5_rd_rep(context, + ctx->auth_context, + &indata, + &repl); + if (kret) { + ret = _gsskrb5_decapsulate(minor_status, + input_token, + &indata, + "\x03\x00", + GSS_KRB5_MECHANISM); if (ret == GSS_S_COMPLETE) { - *minor_status = handle_error_packet(context, ctx, indata); - return GSS_S_FAILURE; + *minor_status = handle_error_packet(context, ctx, indata); + } else { + *minor_status = kret; } - } else if (kret) { - *minor_status = kret; return GSS_S_FAILURE; } } else { diff --git a/source4/heimdal/lib/hcrypto/dh-imath.c b/source4/heimdal/lib/hcrypto/dh-imath.c deleted file mode 100644 index c2e86fa2fa..0000000000 --- a/source4/heimdal/lib/hcrypto/dh-imath.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2006 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -#include -#include -#include - -#ifdef USE_HCRYPTO_IMATH - -#include - -#include "imath/imath.h" - -static void -BN2mpz(mpz_t *s, const BIGNUM *bn) -{ - size_t len; - void *p; - - len = BN_num_bytes(bn); - p = malloc(len); - BN_bn2bin(bn, p); - mp_int_read_unsigned(s, p, len); - free(p); -} - - -static BIGNUM * -mpz2BN(mpz_t *s) -{ - size_t size; - BIGNUM *bn; - void *p; - - size = mp_int_unsigned_len(s); - p = malloc(size); - if (p == NULL && size != 0) - return NULL; - mp_int_to_unsigned(s, p, size); - - bn = BN_bin2bn(p, size, NULL); - free(p); - return bn; -} - -/* - * - */ - -#define DH_NUM_TRIES 10 - -static int -dh_generate_key(DH *dh) -{ - mpz_t pub, priv_key, g, p; - int have_private_key = (dh->priv_key != NULL); - int codes, times = 0; - mp_result res; - - if (dh->p == NULL || dh->g == NULL) - return 0; - - while (times++ < DH_NUM_TRIES) { - if (!have_private_key) { - size_t bits = BN_num_bits(dh->p); - - if (dh->priv_key) - BN_free(dh->priv_key); - - dh->priv_key = BN_new(); - if (dh->priv_key == NULL) - return 0; - if (!BN_rand(dh->priv_key, bits - 1, 0, 0)) { - BN_clear_free(dh->priv_key); - dh->priv_key = NULL; - return 0; - } - } - if (dh->pub_key) - BN_free(dh->pub_key); - - mp_int_init(&pub); - mp_int_init(&priv_key); - mp_int_init(&g); - mp_int_init(&p); - - BN2mpz(&priv_key, dh->priv_key); - BN2mpz(&g, dh->g); - BN2mpz(&p, dh->p); - - res = mp_int_exptmod(&g, &priv_key, &p, &pub); - - mp_int_clear(&priv_key); - mp_int_clear(&g); - mp_int_clear(&p); - if (res != MP_OK) - continue; - - dh->pub_key = mpz2BN(&pub); - mp_int_clear(&pub); - if (dh->pub_key == NULL) - return 0; - - if (DH_check_pubkey(dh, dh->pub_key, &codes) && codes == 0) - break; - if (have_private_key) - return 0; - } - - if (times >= DH_NUM_TRIES) { - if (!have_private_key && dh->priv_key) { - BN_free(dh->priv_key); - dh->priv_key = NULL; - } - if (dh->pub_key) { - BN_free(dh->pub_key); - dh->pub_key = NULL; - } - return 0; - } - - return 1; -} - -static int -dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh) -{ - mpz_t s, priv_key, p, peer_pub; - size_t size = 0; - mp_result res; - - if (dh->pub_key == NULL || dh->g == NULL || dh->priv_key == NULL) - return -1; - - mp_int_init(&p); - BN2mpz(&p, dh->p); - - mp_int_init(&peer_pub); - BN2mpz(&peer_pub, pub); - - /* check if peers pubkey is reasonable */ - if (MP_SIGN(&peer_pub) == MP_NEG - || mp_int_compare(&peer_pub, &p) >= 0 - || mp_int_compare_value(&peer_pub, 1) <= 0) - { - mp_int_clear(&p); - mp_int_clear(&peer_pub); - return -1; - } - - mp_int_init(&priv_key); - BN2mpz(&priv_key, dh->priv_key); - - mp_int_init(&s); - - mp_int_exptmod(&peer_pub, &priv_key, &p, &s); - - mp_int_clear(&p); - mp_int_clear(&peer_pub); - mp_int_clear(&priv_key); - - size = mp_int_unsigned_len(&s); - res = mp_int_to_unsigned(&s, shared, size); - mp_int_clear(&s); - - return (res == MP_OK) ? size : -1; -} - -static int -dh_generate_params(DH *dh, int a, int b, BN_GENCB *callback) -{ - /* groups should already be known, we don't care about this */ - return 0; -} - -static int -dh_init(DH *dh) -{ - return 1; -} - -static int -dh_finish(DH *dh) -{ - return 1; -} - - -/* - * - */ - -const DH_METHOD _hc_dh_imath_method = { - "hcrypto imath DH", - dh_generate_key, - dh_compute_key, - NULL, - dh_init, - dh_finish, - 0, - NULL, - dh_generate_params -}; -#endif /* USE_HCRYPTO_DH_IMATH */ - -/** - * DH implementation using libimath. - * - * @return the DH_METHOD for the DH implementation using libimath. - * - * @ingroup hcrypto_dh - */ - -const DH_METHOD * -DH_imath_method(void) -{ -#ifdef USE_HCRYPTO_DH_IMATH - return &_hc_dh_imath_method; -#else - return NULL; -#endif -} diff --git a/source4/heimdal/lib/hcrypto/dh-ltm.c b/source4/heimdal/lib/hcrypto/dh-ltm.c index 6166100b08..f66cd5aff2 100644 --- a/source4/heimdal/lib/hcrypto/dh-ltm.c +++ b/source4/heimdal/lib/hcrypto/dh-ltm.c @@ -119,14 +119,12 @@ ltm_dh_generate_key(DH *dh) res = mp_exptmod(&g, &priv_key, &p, &pub); - mp_zero(&priv_key); - mp_zero(&g); - mp_zero(&p); + mp_clear_multi(&priv_key, &g, &p, NULL); if (res != 0) continue; dh->pub_key = mpz2BN(&pub); - mp_zero(&pub); + mp_clear(&pub); if (dh->pub_key == NULL) return 0; @@ -155,16 +153,13 @@ static int ltm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh) { mp_int s, priv_key, p, peer_pub; - size_t size = 0; int ret; if (dh->pub_key == NULL || dh->g == NULL || dh->priv_key == NULL) return -1; - mp_init(&p); + mp_init_multi(&s, &priv_key, &p, &peer_pub, NULL); BN2mpz(&p, dh->p); - - mp_init(&peer_pub); BN2mpz(&peer_pub, pub); /* check if peers pubkey is reasonable */ @@ -172,30 +167,26 @@ ltm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh) || mp_cmp(&peer_pub, &p) >= 0 || mp_cmp_d(&peer_pub, 1) <= 0) { - mp_zero(&p); - mp_zero(&peer_pub); - return -1; + ret = -1; + goto out; } - mp_init(&priv_key); BN2mpz(&priv_key, dh->priv_key); - mp_init(&s); - ret = mp_exptmod(&peer_pub, &priv_key, &p, &s); - mp_zero(&p); - mp_zero(&peer_pub); - mp_zero(&priv_key); - - if (ret != 0) - return -1; + if (ret != 0) { + ret = -1; + goto out; + } - size = mp_unsigned_bin_size(&s); + ret = mp_unsigned_bin_size(&s); mp_to_unsigned_bin(&s, shared); - mp_zero(&s); - return size; + out: + mp_clear_multi(&s, &priv_key, &p, &peer_pub, NULL); + + return ret; } static int @@ -235,9 +226,9 @@ const DH_METHOD _hc_dh_ltm_method = { }; /** - * DH implementation using libimath. + * DH implementation using libtommath. * - * @return the DH_METHOD for the DH implementation using libimath. + * @return the DH_METHOD for the DH implementation using libtommath. * * @ingroup hcrypto_dh */ diff --git a/source4/heimdal/lib/hcrypto/dh.c b/source4/heimdal/lib/hcrypto/dh.c index 3ad37f87a7..43e1d6ac1b 100644 --- a/source4/heimdal/lib/hcrypto/dh.c +++ b/source4/heimdal/lib/hcrypto/dh.c @@ -304,7 +304,7 @@ DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes) if (!BN_set_word(bn, 2)) goto out; - if (BN_cmp(bn, pub_key) == 0) { + if (BN_cmp(bn, dh->g) == 0) { unsigned i, n = BN_num_bits(pub_key); unsigned bits = 0; @@ -312,7 +312,7 @@ DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes) if (BN_is_bit_set(pub_key, i)) bits++; - if (bits > 1) { + if (bits < 2) { *codes |= DH_CHECK_PUBKEY_TOO_SMALL; goto out; } @@ -445,8 +445,8 @@ static const DH_METHOD dh_null_method = { dh_null_generate_params }; -extern const DH_METHOD _hc_dh_imath_method; -static const DH_METHOD *dh_default_method = &_hc_dh_imath_method; +extern const DH_METHOD _hc_dh_ltm_method; +static const DH_METHOD *dh_default_method = &_hc_dh_ltm_method; /** * Return the dummy DH implementation. diff --git a/source4/heimdal/lib/hcrypto/dh.h b/source4/heimdal/lib/hcrypto/dh.h index 3a24f9dfdf..637f218bcf 100644 --- a/source4/heimdal/lib/hcrypto/dh.h +++ b/source4/heimdal/lib/hcrypto/dh.h @@ -40,7 +40,6 @@ /* symbol renaming */ #define DH_null_method hc_DH_null_method -#define DH_imath_method hc_DH_imath_method #define DH_tfm_method hc_DH_tfm_method #define DH_ltm_method hc_DH_ltm_method #define DH_new hc_DH_new @@ -119,7 +118,6 @@ struct DH { const DH_METHOD *DH_null_method(void); const DH_METHOD *DH_tfm_method(void); const DH_METHOD *DH_ltm_method(void); -const DH_METHOD *DH_imath_method(void); DH * DH_new(void); DH * DH_new_method(ENGINE *); diff --git a/source4/heimdal/lib/hcrypto/engine.c b/source4/heimdal/lib/hcrypto/engine.c index 6e3e5e3939..15853420f6 100644 --- a/source4/heimdal/lib/hcrypto/engine.c +++ b/source4/heimdal/lib/hcrypto/engine.c @@ -284,26 +284,6 @@ ENGINE_load_builtin_engines(void) ENGINE_finish(engine); #endif -#ifdef USE_HCRYPTO_IMATH - /* - * imath - */ - - engine = ENGINE_new(); - if (engine == NULL) - return; - - ENGINE_set_id(engine, "imath"); - ENGINE_set_name(engine, - "Heimdal crypto imath engine version " PACKAGE_VERSION); - ENGINE_set_RSA(engine, RSA_imath_method()); - ENGINE_set_DH(engine, DH_imath_method()); - - ret = add_engine(engine); - if (ret != 1) - ENGINE_finish(engine); -#endif - #ifdef HAVE_GMP /* * gmp diff --git a/source4/heimdal/lib/hcrypto/imath/LICENSE b/source4/heimdal/lib/hcrypto/imath/LICENSE deleted file mode 100644 index 5b0104fa1b..0000000000 --- a/source4/heimdal/lib/hcrypto/imath/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -IMath is Copyright © 2002-2008 Michael J. Fromberger -You may use it subject to the following Licensing Terms: - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/source4/heimdal/lib/hcrypto/imath/imath.c b/source4/heimdal/lib/hcrypto/imath/imath.c deleted file mode 100644 index 0079bafd02..0000000000 --- a/source4/heimdal/lib/hcrypto/imath/imath.c +++ /dev/null @@ -1,3353 +0,0 @@ -/* - Name: imath.c - Purpose: Arbitrary precision integer arithmetic routines. - Author: M. J. Fromberger - Info: $Id: imath.c 826 2009-02-11 16:21:04Z sting $ - - Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved. - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - -#include "imath.h" - -#if DEBUG -#include -#endif - -#include -#include -#include - -#include - -#if DEBUG -#define STATIC /* public */ -#else -#define STATIC static -#endif - -/* {{{ Constants */ - -const mp_result MP_OK = 0; /* no error, all is well */ -const mp_result MP_FALSE = 0; /* boolean false */ -const mp_result MP_TRUE = -1; /* boolean true */ -const mp_result MP_MEMORY = -2; /* out of memory */ -const mp_result MP_RANGE = -3; /* argument out of range */ -const mp_result MP_UNDEF = -4; /* result undefined */ -const mp_result MP_TRUNC = -5; /* output truncated */ -const mp_result MP_BADARG = -6; /* invalid null argument */ -const mp_result MP_MINERR = -6; - -const mp_sign MP_NEG = 1; /* value is strictly negative */ -const mp_sign MP_ZPOS = 0; /* value is non-negative */ - -STATIC const char *s_unknown_err = "unknown result code"; -STATIC const char *s_error_msg[] = { - "error code 0", - "boolean true", - "out of memory", - "argument out of range", - "result undefined", - "output truncated", - "invalid argument", - NULL -}; - -/* }}} */ - -/* Argument checking macros - Use CHECK() where a return value is required; NRCHECK() elsewhere */ -#define CHECK(TEST) assert(TEST) -#define NRCHECK(TEST) assert(TEST) - -/* {{{ Logarithm table for computing output sizes */ - -/* The ith entry of this table gives the value of log_i(2). - - An integer value n requires ceil(log_i(n)) digits to be represented - in base i. Since it is easy to compute lg(n), by counting bits, we - can compute log_i(n) = lg(n) * log_i(2). - - The use of this table eliminates a dependency upon linkage against - the standard math libraries. - */ -STATIC const double s_log2[] = { - 0.000000000, 0.000000000, 1.000000000, 0.630929754, /* 0 1 2 3 */ - 0.500000000, 0.430676558, 0.386852807, 0.356207187, /* 4 5 6 7 */ - 0.333333333, 0.315464877, 0.301029996, 0.289064826, /* 8 9 10 11 */ - 0.278942946, 0.270238154, 0.262649535, 0.255958025, /* 12 13 14 15 */ - 0.250000000, 0.244650542, 0.239812467, 0.235408913, /* 16 17 18 19 */ - 0.231378213, 0.227670249, 0.224243824, 0.221064729, /* 20 21 22 23 */ - 0.218104292, 0.215338279, 0.212746054, 0.210309918, /* 24 25 26 27 */ - 0.208014598, 0.205846832, 0.203795047, 0.201849087, /* 28 29 30 31 */ - 0.200000000, 0.198239863, 0.196561632, 0.194959022, /* 32 33 34 35 */ - 0.193426404, /* 36 */ -}; - -/* }}} */ -/* {{{ Various macros */ - -/* Return the number of digits needed to represent a static value */ -#define MP_VALUE_DIGITS(V) \ -((sizeof(V)+(sizeof(mp_digit)-1))/sizeof(mp_digit)) - -/* Round precision P to nearest word boundary */ -#define ROUND_PREC(P) ((mp_size)(2*(((P)+1)/2))) - -/* Set array P of S digits to zero */ -#define ZERO(P, S) \ -do{mp_size i__=(S)*sizeof(mp_digit);mp_digit *p__=(P);memset(p__,0,i__);}while(0) - -/* Copy S digits from array P to array Q */ -#define COPY(P, Q, S) \ -do{mp_size i__=(S)*sizeof(mp_digit);mp_digit *p__=(P),*q__=(Q);\ -memcpy(q__,p__,i__);}while(0) - -/* Reverse N elements of type T in array A */ -#define REV(T, A, N) \ -do{T *u_=(A),*v_=u_+(N)-1;while(u_ 1 && (*dz_-- == 0)) --uz_;MP_USED(z_)=uz_;}while(0) - -/* Select min/max. Do not provide expressions for which multiple - evaluation would be problematic, e.g. x++ */ -#define MIN(A, B) ((B)<(A)?(B):(A)) -#define MAX(A, B) ((B)>(A)?(B):(A)) - -/* Exchange lvalues A and B of type T, e.g. - SWAP(int, x, y) where x and y are variables of type int. */ -#define SWAP(T, A, B) do{T t_=(A);A=(B);B=t_;}while(0) - -/* Used to set up and access simple temp stacks within functions. */ -#define TEMP(K) (temp + (K)) -#define SETUP(E, C) \ -do{if((res = (E)) != MP_OK) goto CLEANUP; ++(C);}while(0) - -/* Compare value to zero. */ -#define CMPZ(Z) \ -(((Z)->used==1&&(Z)->digits[0]==0)?0:((Z)->sign==MP_NEG)?-1:1) - -/* Multiply X by Y into Z, ignoring signs. Requires that Z have - enough storage preallocated to hold the result. */ -#define UMUL(X, Y, Z) \ -do{mp_size ua_=MP_USED(X),ub_=MP_USED(Y);mp_size o_=ua_+ub_;\ -ZERO(MP_DIGITS(Z),o_);\ -(void) s_kmul(MP_DIGITS(X),MP_DIGITS(Y),MP_DIGITS(Z),ua_,ub_);\ -MP_USED(Z)=o_;CLAMP(Z);}while(0) - -/* Square X into Z. Requires that Z have enough storage to hold the - result. */ -#define USQR(X, Z) \ -do{mp_size ua_=MP_USED(X),o_=ua_+ua_;ZERO(MP_DIGITS(Z),o_);\ -(void) s_ksqr(MP_DIGITS(X),MP_DIGITS(Z),ua_);MP_USED(Z)=o_;CLAMP(Z);}while(0) - -#define UPPER_HALF(W) ((mp_word)((W) >> MP_DIGIT_BIT)) -#define LOWER_HALF(W) ((mp_digit)(W)) -#define HIGH_BIT_SET(W) ((W) >> (MP_WORD_BIT - 1)) -#define ADD_WILL_OVERFLOW(W, V) ((MP_WORD_MAX - (V)) < (W)) - -/* }}} */ -/* {{{ Default configuration settings */ - -/* Default number of digits allocated to a new mp_int */ -#if IMATH_TEST -mp_size default_precision = MP_DEFAULT_PREC; -#else -STATIC const mp_size default_precision = MP_DEFAULT_PREC; -#endif - -/* Minimum number of digits to invoke recursive multiply */ -#if IMATH_TEST -mp_size multiply_threshold = MP_MULT_THRESH; -#else -STATIC const mp_size multiply_threshold = MP_MULT_THRESH; -#endif - -/* }}} */ - -/* Allocate a buffer of (at least) num digits, or return - NULL if that couldn't be done. */ -STATIC mp_digit *s_alloc(mp_size num); - -/* Release a buffer of digits allocated by s_alloc(). */ -STATIC void s_free(void *ptr); - -/* Insure that z has at least min digits allocated, resizing if - necessary. Returns true if successful, false if out of memory. */ -STATIC int s_pad(mp_int z, mp_size min); - -/* Fill in a "fake" mp_int on the stack with a given value */ -STATIC void s_fake(mp_int z, mp_small value, mp_digit vbuf[]); - -/* Compare two runs of digits of given length, returns <0, 0, >0 */ -STATIC int s_cdig(mp_digit *da, mp_digit *db, mp_size len); - -/* Pack the unsigned digits of v into array t */ -STATIC int s_vpack(mp_small v, mp_digit t[]); - -/* Compare magnitudes of a and b, returns <0, 0, >0 */ -STATIC int s_ucmp(mp_int a, mp_int b); - -/* Compare magnitudes of a and v, returns <0, 0, >0 */ -STATIC int s_vcmp(mp_int a, mp_small v); - -/* Unsigned magnitude addition; assumes dc is big enough. - Carry out is returned (no memory allocated). */ -STATIC mp_digit s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc, - mp_size size_a, mp_size size_b); - -/* Unsigned magnitude subtraction. Assumes dc is big enough. */ -STATIC void s_usub(mp_digit *da, mp_digit *db, mp_digit *dc, - mp_size size_a, mp_size size_b); - -/* Unsigned recursive multiplication. Assumes dc is big enough. */ -STATIC int s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc, - mp_size size_a, mp_size size_b); - -/* Unsigned magnitude multiplication. Assumes dc is big enough. */ -STATIC void s_umul(mp_digit *da, mp_digit *db, mp_digit *dc, - mp_size size_a, mp_size size_b); - -/* Unsigned recursive squaring. Assumes dc is big enough. */ -STATIC int s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a); - -/* Unsigned magnitude squaring. Assumes dc is big enough. */ -STATIC void s_usqr(mp_digit *da, mp_digit *dc, mp_size size_a); - -/* Single digit addition. Assumes a is big enough. */ -STATIC void s_dadd(mp_int a, mp_digit b); - -/* Single digit multiplication. Assumes a is big enough. */ -STATIC void s_dmul(mp_int a, mp_digit b); - -/* Single digit multiplication on buffers; assumes dc is big enough. */ -STATIC void s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc, - mp_size size_a); - -/* Single digit division. Replaces a with the quotient, - returns the remainder. */ -STATIC mp_digit s_ddiv(mp_int a, mp_digit b); - -/* Quick division by a power of 2, replaces z (no allocation) */ -STATIC void s_qdiv(mp_int z, mp_size p2); - -/* Quick remainder by a power of 2, replaces z (no allocation) */ -STATIC void s_qmod(mp_int z, mp_size p2); - -/* Quick multiplication by a power of 2, replaces z. - Allocates if necessary; returns false in case this fails. */ -STATIC int s_qmul(mp_int z, mp_size p2); - -/* Quick subtraction from a power of 2, replaces z. - Allocates if necessary; returns false in case this fails. */ -STATIC int s_qsub(mp_int z, mp_size p2); - -/* Return maximum k such that 2^k divides z. */ -STATIC int s_dp2k(mp_int z); - -/* Return k >= 0 such that z = 2^k, or -1 if there is no such k. */ -STATIC int s_isp2(mp_int z); - -/* Set z to 2^k. May allocate; returns false in case this fails. */ -STATIC int s_2expt(mp_int z, mp_small k); - -/* Normalize a and b for division, returns normalization constant */ -STATIC int s_norm(mp_int a, mp_int b); - -/* Compute constant mu for Barrett reduction, given modulus m, result - replaces z, m is untouched. */ -STATIC mp_result s_brmu(mp_int z, mp_int m); - -/* Reduce a modulo m, using Barrett's algorithm. */ -STATIC int s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2); - -/* Modular exponentiation, using Barrett reduction */ -STATIC mp_result s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c); - -/* Unsigned magnitude division. Assumes |a| > |b|. Allocates - temporaries; overwrites a with quotient, b with remainder. */ -STATIC mp_result s_udiv(mp_int a, mp_int b); - -/* Compute the number of digits in radix r required to represent the - given value. Does not account for sign flags, terminators, etc. */ -STATIC int s_outlen(mp_int z, mp_size r); - -/* Guess how many digits of precision will be needed to represent a - radix r value of the specified number of digits. Returns a value - guaranteed to be no smaller than the actual number required. */ -STATIC mp_size s_inlen(int len, mp_size r); - -/* Convert a character to a digit value in radix r, or - -1 if out of range */ -STATIC int s_ch2val(char c, int r); - -/* Convert a digit value to a character */ -STATIC char s_val2ch(int v, int caps); - -/* Take 2's complement of a buffer in place */ -STATIC void s_2comp(unsigned char *buf, int len); - -/* Convert a value to binary, ignoring sign. On input, *limpos is the - bound on how many bytes should be written to buf; on output, *limpos - is set to the number of bytes actually written. */ -STATIC mp_result s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad); - -#if DEBUG -/* Dump a representation of the mp_int to standard output */ -void s_print(char *tag, mp_int z); -void s_print_buf(char *tag, mp_digit *buf, mp_size num); -#endif - -/* {{{ mp_int_init(z) */ - -mp_result mp_int_init(mp_int z) -{ - if(z == NULL) - return MP_BADARG; - - z->single = 0; - z->digits = &(z->single); - z->alloc = 1; - z->used = 1; - z->sign = MP_ZPOS; - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_alloc() */ - -mp_int mp_int_alloc(void) -{ - mp_int out = malloc(sizeof(mpz_t)); - - if(out != NULL) - mp_int_init(out); - - return out; -} - -/* }}} */ - -/* {{{ mp_int_init_size(z, prec) */ - -mp_result mp_int_init_size(mp_int z, mp_size prec) -{ - CHECK(z != NULL); - - if(prec == 0) - prec = default_precision; - else if(prec == 1) - return mp_int_init(z); - else - prec = (mp_size) ROUND_PREC(prec); - - if((MP_DIGITS(z) = s_alloc(prec)) == NULL) - return MP_MEMORY; - - z->digits[0] = 0; - MP_USED(z) = 1; - MP_ALLOC(z) = prec; - MP_SIGN(z) = MP_ZPOS; - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_init_copy(z, old) */ - -mp_result mp_int_init_copy(mp_int z, mp_int old) -{ - mp_result res; - mp_size uold; - - CHECK(z != NULL && old != NULL); - - uold = MP_USED(old); - if(uold == 1) { - mp_int_init(z); - } - else { - mp_size target = MAX(uold, default_precision); - - if((res = mp_int_init_size(z, target)) != MP_OK) - return res; - } - - MP_USED(z) = uold; - MP_SIGN(z) = MP_SIGN(old); - COPY(MP_DIGITS(old), MP_DIGITS(z), uold); - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_init_value(z, value) */ - -mp_result mp_int_init_value(mp_int z, mp_small value) -{ - mpz_t vtmp; - mp_digit vbuf[MP_VALUE_DIGITS(value)]; - - s_fake(&vtmp, value, vbuf); - return mp_int_init_copy(z, &vtmp); -} - -/* }}} */ - -/* {{{ mp_int_set_value(z, value) */ - -mp_result mp_int_set_value(mp_int z, mp_small value) -{ - mpz_t vtmp; - mp_digit vbuf[MP_VALUE_DIGITS(value)]; - - s_fake(&vtmp, value, vbuf); - return mp_int_copy(&vtmp, z); -} - -/* }}} */ - -/* {{{ mp_int_clear(z) */ - -void mp_int_clear(mp_int z) -{ - if(z == NULL) - return; - - if(MP_DIGITS(z) != NULL) { - if((void *) MP_DIGITS(z) != (void *) z) - s_free(MP_DIGITS(z)); - - MP_DIGITS(z) = NULL; - } -} - -/* }}} */ - -/* {{{ mp_int_free(z) */ - -void mp_int_free(mp_int z) -{ - NRCHECK(z != NULL); - - mp_int_clear(z); - free(z); /* note: NOT s_free() */ -} - -/* }}} */ - -/* {{{ mp_int_copy(a, c) */ - -mp_result mp_int_copy(mp_int a, mp_int c) -{ - CHECK(a != NULL && c != NULL); - - if(a != c) { - mp_size ua = MP_USED(a); - mp_digit *da, *dc; - - if(!s_pad(c, ua)) - return MP_MEMORY; - - da = MP_DIGITS(a); dc = MP_DIGITS(c); - COPY(da, dc, ua); - - MP_USED(c) = ua; - MP_SIGN(c) = MP_SIGN(a); - } - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_swap(a, c) */ - -void mp_int_swap(mp_int a, mp_int c) -{ - if(a != c) { - mpz_t tmp = *a; - - *a = *c; - *c = tmp; - } -} - -/* }}} */ - -/* {{{ mp_int_zero(z) */ - -void mp_int_zero(mp_int z) -{ - NRCHECK(z != NULL); - - z->digits[0] = 0; - MP_USED(z) = 1; - MP_SIGN(z) = MP_ZPOS; -} - -/* }}} */ - -/* {{{ mp_int_abs(a, c) */ - -mp_result mp_int_abs(mp_int a, mp_int c) -{ - mp_result res; - - CHECK(a != NULL && c != NULL); - - if((res = mp_int_copy(a, c)) != MP_OK) - return res; - - MP_SIGN(c) = MP_ZPOS; - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_neg(a, c) */ - -mp_result mp_int_neg(mp_int a, mp_int c) -{ - mp_result res; - - CHECK(a != NULL && c != NULL); - - if((res = mp_int_copy(a, c)) != MP_OK) - return res; - - if(CMPZ(c) != 0) - MP_SIGN(c) = 1 - MP_SIGN(a); - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_add(a, b, c) */ - -mp_result mp_int_add(mp_int a, mp_int b, mp_int c) -{ - mp_size ua, ub, max; - - CHECK(a != NULL && b != NULL && c != NULL); - - ua = MP_USED(a); ub = MP_USED(b); - max = MAX(ua, ub); - - if(MP_SIGN(a) == MP_SIGN(b)) { - /* Same sign -- add magnitudes, preserve sign of addends */ - mp_digit carry; - mp_size uc; - - if(!s_pad(c, max)) - return MP_MEMORY; - - carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub); - uc = max; - - if(carry) { - if(!s_pad(c, max + 1)) - return MP_MEMORY; - - c->digits[max] = carry; - ++uc; - } - - MP_USED(c) = uc; - MP_SIGN(c) = MP_SIGN(a); - - } - else { - /* Different signs -- subtract magnitudes, preserve sign of greater */ - mp_int x, y; - int cmp = s_ucmp(a, b); /* magnitude comparision, sign ignored */ - - /* Set x to max(a, b), y to min(a, b) to simplify later code. - A special case yields zero for equal magnitudes. - */ - if(cmp == 0) { - mp_int_zero(c); - return MP_OK; - } - else if(cmp < 0) { - x = b; y = a; - } - else { - x = a; y = b; - } - - if(!s_pad(c, MP_USED(x))) - return MP_MEMORY; - - /* Subtract smaller from larger */ - s_usub(MP_DIGITS(x), MP_DIGITS(y), MP_DIGITS(c), MP_USED(x), MP_USED(y)); - MP_USED(c) = MP_USED(x); - CLAMP(c); - - /* Give result the sign of the larger */ - MP_SIGN(c) = MP_SIGN(x); - } - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_add_value(a, value, c) */ - -mp_result mp_int_add_value(mp_int a, mp_small value, mp_int c) -{ - mpz_t vtmp; - mp_digit vbuf[MP_VALUE_DIGITS(value)]; - - s_fake(&vtmp, value, vbuf); - - return mp_int_add(a, &vtmp, c); -} - -/* }}} */ - -/* {{{ mp_int_sub(a, b, c) */ - -mp_result mp_int_sub(mp_int a, mp_int b, mp_int c) -{ - mp_size ua, ub, max; - - CHECK(a != NULL && b != NULL && c != NULL); - - ua = MP_USED(a); ub = MP_USED(b); - max = MAX(ua, ub); - - if(MP_SIGN(a) != MP_SIGN(b)) { - /* Different signs -- add magnitudes and keep sign of a */ - mp_digit carry; - mp_size uc; - - if(!s_pad(c, max)) - return MP_MEMORY; - - carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub); - uc = max; - - if(carry) { - if(!s_pad(c, max + 1)) - return MP_MEMORY; - - c->digits[max] = carry; - ++uc; - } - - MP_USED(c) = uc; - MP_SIGN(c) = MP_SIGN(a); - - } - else { - /* Same signs -- subtract magnitudes */ - mp_int x, y; - mp_sign osign; - int cmp = s_ucmp(a, b); - - if(!s_pad(c, max)) - return MP_MEMORY; - - if(cmp >= 0) { - x = a; y = b; osign = MP_ZPOS; - } - else { - x = b; y = a; osign = MP_NEG; - } - - if(MP_SIGN(a) == MP_NEG && cmp != 0) - osign = 1 - osign; - - s_usub(MP_DIGITS(x), MP_DIGITS(y), MP_DIGITS(c), MP_USED(x), MP_USED(y)); - MP_USED(c) = MP_USED(x); - CLAMP(c); - - MP_SIGN(c) = osign; - } - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_sub_value(a, value, c) */ - -mp_result mp_int_sub_value(mp_int a, mp_small value, mp_int c) -{ - mpz_t vtmp; - mp_digit vbuf[MP_VALUE_DIGITS(value)]; - - s_fake(&vtmp, value, vbuf); - - return mp_int_sub(a, &vtmp, c); -} - -/* }}} */ - -/* {{{ mp_int_mul(a, b, c) */ - -mp_result mp_int_mul(mp_int a, mp_int b, mp_int c) -{ - mp_digit *out; - mp_size osize, ua, ub, p = 0; - mp_sign osign; - - CHECK(a != NULL && b != NULL && c != NULL); - - /* If either input is zero, we can shortcut multiplication */ - if(mp_int_compare_zero(a) == 0 || mp_int_compare_zero(b) == 0) { - mp_int_zero(c); - return MP_OK; - } - - /* Output is positive if inputs have same sign, otherwise negative */ - osign = (MP_SIGN(a) == MP_SIGN(b)) ? MP_ZPOS : MP_NEG; - - /* If the output is not identical to any of the inputs, we'll write - the results directly; otherwise, allocate a temporary space. */ - ua = MP_USED(a); ub = MP_USED(b); - osize = MAX(ua, ub); - osize = 4 * ((osize + 1) / 2); - - if(c == a || c == b) { - p = ROUND_PREC(osize); - p = MAX(p, default_precision); - - if((out = s_alloc(p)) == NULL) - return MP_MEMORY; - } - else { - if(!s_pad(c, osize)) - return MP_MEMORY; - - out = MP_DIGITS(c); - } - ZERO(out, osize); - - if(!s_kmul(MP_DIGITS(a), MP_DIGITS(b), out, ua, ub)) - return MP_MEMORY; - - /* If we allocated a new buffer, get rid of whatever memory c was - already using, and fix up its fields to reflect that. - */ - if(out != MP_DIGITS(c)) { - if((void *) MP_DIGITS(c) != (void *) c) - s_free(MP_DIGITS(c)); - MP_DIGITS(c) = out; - MP_ALLOC(c) = p; - } - - MP_USED(c) = osize; /* might not be true, but we'll fix it ... */ - CLAMP(c); /* ... right here */ - MP_SIGN(c) = osign; - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_mul_value(a, value, c) */ - -mp_result mp_int_mul_value(mp_int a, mp_small value, mp_int c) -{ - mpz_t vtmp; - mp_digit vbuf[MP_VALUE_DIGITS(value)]; - - s_fake(&vtmp, value, vbuf); - - return mp_int_mul(a, &vtmp, c); -} - -/* }}} */ - -/* {{{ mp_int_mul_pow2(a, p2, c) */ - -mp_result mp_int_mul_pow2(mp_int a, mp_small p2, mp_int c) -{ - mp_result res; - CHECK(a != NULL && c != NULL && p2 >= 0); - - if((res = mp_int_copy(a, c)) != MP_OK) - return res; - - if(s_qmul(c, (mp_size) p2)) - return MP_OK; - else - return MP_MEMORY; -} - -/* }}} */ - -/* {{{ mp_int_sqr(a, c) */ - -mp_result mp_int_sqr(mp_int a, mp_int c) -{ - mp_digit *out; - mp_size osize, p = 0; - - CHECK(a != NULL && c != NULL); - - /* Get a temporary buffer big enough to hold the result */ - osize = (mp_size) 4 * ((MP_USED(a) + 1) / 2); - if(a == c) { - p = ROUND_PREC(osize); - p = MAX(p, default_precision); - - if((out = s_alloc(p)) == NULL) - return MP_MEMORY; - } - else { - if(!s_pad(c, osize)) - return MP_MEMORY; - - out = MP_DIGITS(c); - } - ZERO(out, osize); - - s_ksqr(MP_DIGITS(a), out, MP_USED(a)); - - /* Get rid of whatever memory c was already using, and fix up its - fields to reflect the new digit array it's using - */ - if(out != MP_DIGITS(c)) { - if((void *) MP_DIGITS(c) != (void *) c) - s_free(MP_DIGITS(c)); - MP_DIGITS(c) = out; - MP_ALLOC(c) = p; - } - - MP_USED(c) = osize; /* might not be true, but we'll fix it ... */ - CLAMP(c); /* ... right here */ - MP_SIGN(c) = MP_ZPOS; - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_div(a, b, q, r) */ - -mp_result mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r) -{ - int cmp, last = 0, lg; - mp_result res = MP_OK; - mpz_t temp[2]; - mp_int qout, rout; - mp_sign sa = MP_SIGN(a), sb = MP_SIGN(b); - - CHECK(a != NULL && b != NULL && q != r); - - if(CMPZ(b) == 0) - return MP_UNDEF; - else if((cmp = s_ucmp(a, b)) < 0) { - /* If |a| < |b|, no division is required: - q = 0, r = a - */ - if(r && (res = mp_int_copy(a, r)) != MP_OK) - return res; - - if(q) - mp_int_zero(q); - - return MP_OK; - } - else if(cmp == 0) { - /* If |a| = |b|, no division is required: - q = 1 or -1, r = 0 - */ - if(r) - mp_int_zero(r); - - if(q) { - mp_int_zero(q); - q->digits[0] = 1; - - if(sa != sb) - MP_SIGN(q) = MP_NEG; - } - - return MP_OK; - } - - /* When |a| > |b|, real division is required. We need someplace to - store quotient and remainder, but q and r are allowed to be NULL - or to overlap with the inputs. - */ - if((lg = s_isp2(b)) < 0) { - if(q && b != q) { - if((res = mp_int_copy(a, q)) != MP_OK) - goto CLEANUP; - else - qout = q; - } - else { - qout = TEMP(last); - SETUP(mp_int_init_copy(TEMP(last), a), last); - } - - if(r && a != r) { - if((res = mp_int_copy(b, r)) != MP_OK) - goto CLEANUP; - else - rout = r; - } - else { - rout = TEMP(last); - SETUP(mp_int_init_copy(TEMP(last), b), last); - } - - if((res = s_udiv(qout, rout)) != MP_OK) goto CLEANUP; - } - else { - if(q && (res = mp_int_copy(a, q)) != MP_OK) goto CLEANUP; - if(r && (res = mp_int_copy(a, r)) != MP_OK) goto CLEANUP; - - if(q) s_qdiv(q, (mp_size) lg); qout = q; - if(r) s_qmod(r, (mp_size) lg); rout = r; - } - - /* Recompute signs for output */ - if(rout) { - MP_SIGN(rout) = sa; - if(CMPZ(rout) == 0) - MP_SIGN(rout) = MP_ZPOS; - } - if(qout) { - MP_SIGN(qout) = (sa == sb) ? MP_ZPOS : MP_NEG; - if(CMPZ(qout) == 0) - MP_SIGN(qout) = MP_ZPOS; - } - - if(q && (res = mp_int_copy(qout, q)) != MP_OK) goto CLEANUP; - if(r && (res = mp_int_copy(rout, r)) != MP_OK) goto CLEANUP; - - CLEANUP: - while(--last >= 0) - mp_int_clear(TEMP(last)); - - return res; -} - -/* }}} */ - -/* {{{ mp_int_mod(a, m, c) */ - -mp_result mp_int_mod(mp_int a, mp_int m, mp_int c) -{ - mp_result res; - mpz_t tmp; - mp_int out; - - if(m == c) { - mp_int_init(&tmp); - out = &tmp; - } - else { - out = c; - } - - if((res = mp_int_div(a, m, NULL, out)) != MP_OK) - goto CLEANUP; - - if(CMPZ(out) < 0) - res = mp_int_add(out, m, c); - else - res = mp_int_copy(out, c); - - CLEANUP: - if(out != c) - mp_int_clear(&tmp); - - return res; -} - -/* }}} */ - -/* {{{ mp_int_div_value(a, value, q, r) */ - -mp_result mp_int_div_value(mp_int a, mp_small value, mp_int q, mp_small *r) -{ - mpz_t vtmp, rtmp; - mp_digit vbuf[MP_VALUE_DIGITS(value)]; - mp_result res; - - mp_int_init(&rtmp); - s_fake(&vtmp, value, vbuf); - - if((res = mp_int_div(a, &vtmp, q, &rtmp)) != MP_OK) - goto CLEANUP; - - if(r) - (void) mp_int_to_int(&rtmp, r); /* can't fail */ - - CLEANUP: - mp_int_clear(&rtmp); - return res; -} - -/* }}} */ - -/* {{{ mp_int_div_pow2(a, p2, q, r) */ - -mp_result mp_int_div_pow2(mp_int a, mp_small p2, mp_int q, mp_int r) -{ - mp_result res = MP_OK; - - CHECK(a != NULL && p2 >= 0 && q != r); - - if(q != NULL && (res = mp_int_copy(a, q)) == MP_OK) - s_qdiv(q, (mp_size) p2); - - if(res == MP_OK && r != NULL && (res = mp_int_copy(a, r)) == MP_OK) - s_qmod(r, (mp_size) p2); - - return res; -} - -/* }}} */ - -/* {{{ mp_int_expt(a, b, c) */ - -mp_result mp_int_expt(mp_int a, mp_small b, mp_int c) -{ - mpz_t t; - mp_result res; - unsigned int v = abs(b); - - CHECK(b >= 0 && c != NULL); - - if((res = mp_int_init_copy(&t, a)) != MP_OK) - return res; - - (void) mp_int_set_value(c, 1); - while(v != 0) { - if(v & 1) { - if((res = mp_int_mul(c, &t, c)) != MP_OK) - goto CLEANUP; - } - - v >>= 1; - if(v == 0) break; - - if((res = mp_int_sqr(&t, &t)) != MP_OK) - goto CLEANUP; - } - - CLEANUP: - mp_int_clear(&t); - return res; -} - -/* }}} */ - -/* {{{ mp_int_expt_value(a, b, c) */ - -mp_result mp_int_expt_value(mp_small a, mp_small b, mp_int c) -{ - mpz_t t; - mp_result res; - unsigned int v = abs(b); - - CHECK(b >= 0 && c != NULL); - - if((res = mp_int_init_value(&t, a)) != MP_OK) - return res; - - (void) mp_int_set_value(c, 1); - while(v != 0) { - if(v & 1) { - if((res = mp_int_mul(c, &t, c)) != MP_OK) - goto CLEANUP; - } - - v >>= 1; - if(v == 0) break; - - if((res = mp_int_sqr(&t, &t)) != MP_OK) - goto CLEANUP; - } - - CLEANUP: - mp_int_clear(&t); - return res; -} - -/* }}} */ - -/* {{{ mp_int_compare(a, b) */ - -int mp_int_compare(mp_int a, mp_int b) -{ - mp_sign sa; - - CHECK(a != NULL && b != NULL); - - sa = MP_SIGN(a); - if(sa == MP_SIGN(b)) { - int cmp = s_ucmp(a, b); - - /* If they're both zero or positive, the normal comparison - applies; if both negative, the sense is reversed. */ - if(sa == MP_ZPOS) - return cmp; - else - return -cmp; - - } - else { - if(sa == MP_ZPOS) - return 1; - else - return -1; - } -} - -/* }}} */ - -/* {{{ mp_int_compare_unsigned(a, b) */ - -int mp_int_compare_unsigned(mp_int a, mp_int b) -{ - NRCHECK(a != NULL && b != NULL); - - return s_ucmp(a, b); -} - -/* }}} */ - -/* {{{ mp_int_compare_zero(z) */ - -int mp_int_compare_zero(mp_int z) -{ - NRCHECK(z != NULL); - - if(MP_USED(z) == 1 && z->digits[0] == 0) - return 0; - else if(MP_SIGN(z) == MP_ZPOS) - return 1; - else - return -1; -} - -/* }}} */ - -/* {{{ mp_int_compare_value(z, value) */ - -int mp_int_compare_value(mp_int z, mp_small value) -{ - mp_sign vsign = (value < 0) ? MP_NEG : MP_ZPOS; - int cmp; - - CHECK(z != NULL); - - if(vsign == MP_SIGN(z)) { - cmp = s_vcmp(z, value); - - if(vsign == MP_ZPOS) - return cmp; - else - return -cmp; - } - else { - if(value < 0) - return 1; - else - return -1; - } -} - -/* }}} */ - -/* {{{ mp_int_exptmod(a, b, m, c) */ - -mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c) -{ - mp_result res; - mp_size um; - mpz_t temp[3]; - mp_int s; - int last = 0; - - CHECK(a != NULL && b != NULL && c != NULL && m != NULL); - - /* Zero moduli and negative exponents are not considered. */ - if(CMPZ(m) == 0) - return MP_UNDEF; - if(CMPZ(b) < 0) - return MP_RANGE; - - um = MP_USED(m); - SETUP(mp_int_init_size(TEMP(0), 2 * um), last); - SETUP(mp_int_init_size(TEMP(1), 2 * um), last); - - if(c == b || c == m) { - SETUP(mp_int_init_size(TEMP(2), 2 * um), last); - s = TEMP(2); - } - else { - s = c; - } - - if((res = mp_int_mod(a, m, TEMP(0))) != MP_OK) goto CLEANUP; - - if((res = s_brmu(TEMP(1), m)) != MP_OK) goto CLEANUP; - - if((res = s_embar(TEMP(0), b, m, TEMP(1), s)) != MP_OK) - goto CLEANUP; - - res = mp_int_copy(s, c); - - CLEANUP: - while(--last >= 0) - mp_int_clear(TEMP(last)); - - return res; -} - -/* }}} */ - -/* {{{ mp_int_exptmod_evalue(a, value, m, c) */ - -mp_result mp_int_exptmod_evalue(mp_int a, mp_small value, mp_int m, mp_int c) -{ - mpz_t vtmp; - mp_digit vbuf[MP_VALUE_DIGITS(value)]; - - s_fake(&vtmp, value, vbuf); - - return mp_int_exptmod(a, &vtmp, m, c); -} - -/* }}} */ - -/* {{{ mp_int_exptmod_bvalue(v, b, m, c) */ - -mp_result mp_int_exptmod_bvalue(mp_small value, mp_int b, - mp_int m, mp_int c) -{ - mpz_t vtmp; - mp_digit vbuf[MP_VALUE_DIGITS(value)]; - - s_fake(&vtmp, value, vbuf); - - return mp_int_exptmod(&vtmp, b, m, c); -} - -/* }}} */ - -/* {{{ mp_int_exptmod_known(a, b, m, mu, c) */ - -mp_result mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c) -{ - mp_result res; - mp_size um; - mpz_t temp[2]; - mp_int s; - int last = 0; - - CHECK(a && b && m && c); - - /* Zero moduli and negative exponents are not considered. */ - if(CMPZ(m) == 0) - return MP_UNDEF; - if(CMPZ(b) < 0) - return MP_RANGE; - - um = MP_USED(m); - SETUP(mp_int_init_size(TEMP(0), 2 * um), last); - - if(c == b || c == m) { - SETUP(mp_int_init_size(TEMP(1), 2 * um), last); - s = TEMP(1); - } - else { - s = c; - } - - if((res = mp_int_mod(a, m, TEMP(0))) != MP_OK) goto CLEANUP; - - if((res = s_embar(TEMP(0), b, m, mu, s)) != MP_OK) - goto CLEANUP; - - res = mp_int_copy(s, c); - - CLEANUP: - while(--last >= 0) - mp_int_clear(TEMP(last)); - - return res; -} - -/* }}} */ - -/* {{{ mp_int_redux_const(m, c) */ - -mp_result mp_int_redux_const(mp_int m, mp_int c) -{ - CHECK(m != NULL && c != NULL && m != c); - - return s_brmu(c, m); -} - -/* }}} */ - -/* {{{ mp_int_invmod(a, m, c) */ - -mp_result mp_int_invmod(mp_int a, mp_int m, mp_int c) -{ - mp_result res; - mp_sign sa; - int last = 0; - mpz_t temp[2]; - - CHECK(a != NULL && m != NULL && c != NULL); - - if(CMPZ(a) == 0 || CMPZ(m) <= 0) - return MP_RANGE; - - sa = MP_SIGN(a); /* need this for the result later */ - - for(last = 0; last < 2; ++last) - mp_int_init(TEMP(last)); - - if((res = mp_int_egcd(a, m, TEMP(0), TEMP(1), NULL)) != MP_OK) - goto CLEANUP; - - if(mp_int_compare_value(TEMP(0), 1) != 0) { - res = MP_UNDEF; - goto CLEANUP; - } - - /* It is first necessary to constrain the value to the proper range */ - if((res = mp_int_mod(TEMP(1), m, TEMP(1))) != MP_OK) - goto CLEANUP; - - /* Now, if 'a' was originally negative, the value we have is - actually the magnitude of the negative representative; to get the - positive value we have to subtract from the modulus. Otherwise, - the value is okay as it stands. - */ - if(sa == MP_NEG) - res = mp_int_sub(m, TEMP(1), c); - else - res = mp_int_copy(TEMP(1), c); - - CLEANUP: - while(--last >= 0) - mp_int_clear(TEMP(last)); - - return res; -} - -/* }}} */ - -/* {{{ mp_int_gcd(a, b, c) */ - -/* Binary GCD algorithm due to Josef Stein, 1961 */ -mp_result mp_int_gcd(mp_int a, mp_int b, mp_int c) -{ - int ca, cb, k = 0; - mpz_t u, v, t; - mp_result res; - - CHECK(a != NULL && b != NULL && c != NULL); - - ca = CMPZ(a); - cb = CMPZ(b); - if(ca == 0 && cb == 0) - return MP_UNDEF; - else if(ca == 0) - return mp_int_abs(b, c); - else if(cb == 0) - return mp_int_abs(a, c); - - mp_int_init(&t); - if((res = mp_int_init_copy(&u, a)) != MP_OK) - goto U; - if((res = mp_int_init_copy(&v, b)) != MP_OK) - goto V; - - MP_SIGN(&u) = MP_ZPOS; MP_SIGN(&v) = MP_ZPOS; - - { /* Divide out common factors of 2 from u and v */ - int div2_u = s_dp2k(&u), div2_v = s_dp2k(&v); - - k = MIN(div2_u, div2_v); - s_qdiv(&u, (mp_size) k); - s_qdiv(&v, (mp_size) k); - } - - if(mp_int_is_odd(&u)) { - if((res = mp_int_neg(&v, &t)) != MP_OK) - goto CLEANUP; - } - else { - if((res = mp_int_copy(&u, &t)) != MP_OK) - goto CLEANUP; - } - - for(;;) { - s_qdiv(&t, s_dp2k(&t)); - - if(CMPZ(&t) > 0) { - if((res = mp_int_copy(&t, &u)) != MP_OK) - goto CLEANUP; - } - else { - if((res = mp_int_neg(&t, &v)) != MP_OK) - goto CLEANUP; - } - - if((res = mp_int_sub(&u, &v, &t)) != MP_OK) - goto CLEANUP; - - if(CMPZ(&t) == 0) - break; - } - - if((res = mp_int_abs(&u, c)) != MP_OK) - goto CLEANUP; - if(!s_qmul(c, (mp_size) k)) - res = MP_MEMORY; - - CLEANUP: - mp_int_clear(&v); - V: mp_int_clear(&u); - U: mp_int_clear(&t); - - return res; -} - -/* }}} */ - -/* {{{ mp_int_egcd(a, b, c, x, y) */ - -/* This is the binary GCD algorithm again, but this time we keep track - of the elementary matrix operations as we go, so we can get values - x and y satisfying c = ax + by. - */ -mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c, - mp_int x, mp_int y) -{ - int k, last = 0, ca, cb; - mpz_t temp[8]; - mp_result res; - - CHECK(a != NULL && b != NULL && c != NULL && - (x != NULL || y != NULL)); - - ca = CMPZ(a); - cb = CMPZ(b); - if(ca == 0 && cb == 0) - return MP_UNDEF; - else if(ca == 0) { - if((res = mp_int_abs(b, c)) != MP_OK) return res; - mp_int_zero(x); (void) mp_int_set_value(y, 1); return MP_OK; - } - else if(cb == 0) { - if((res = mp_int_abs(a, c)) != MP_OK) return res; - (void) mp_int_set_value(x, 1); mp_int_zero(y); return MP_OK; - } - - /* Initialize temporaries: - A:0, B:1, C:2, D:3, u:4, v:5, ou:6, ov:7 */ - for(last = 0; last < 4; ++last) - mp_int_init(TEMP(last)); - TEMP(0)->digits[0] = 1; - TEMP(3)->digits[0] = 1; - - SETUP(mp_int_init_copy(TEMP(4), a), last); - SETUP(mp_int_init_copy(TEMP(5), b), last); - - /* We will work with absolute values here */ - MP_SIGN(TEMP(4)) = MP_ZPOS; - MP_SIGN(TEMP(5)) = MP_ZPOS; - - { /* Divide out common factors of 2 from u and v */ - int div2_u = s_dp2k(TEMP(4)), div2_v = s_dp2k(TEMP(5)); - - k = MIN(div2_u, div2_v); - s_qdiv(TEMP(4), k); - s_qdiv(TEMP(5), k); - } - - SETUP(mp_int_init_copy(TEMP(6), TEMP(4)), last); - SETUP(mp_int_init_copy(TEMP(7), TEMP(5)), last); - - for(;;) { - while(mp_int_is_even(TEMP(4))) { - s_qdiv(TEMP(4), 1); - - if(mp_int_is_odd(TEMP(0)) || mp_int_is_odd(TEMP(1))) { - if((res = mp_int_add(TEMP(0), TEMP(7), TEMP(0))) != MP_OK) - goto CLEANUP; - if((res = mp_int_sub(TEMP(1), TEMP(6), TEMP(1))) != MP_OK) - goto CLEANUP; - } - - s_qdiv(TEMP(0), 1); - s_qdiv(TEMP(1), 1); - } - - while(mp_int_is_even(TEMP(5))) { - s_qdiv(TEMP(5), 1); - - if(mp_int_is_odd(TEMP(2)) || mp_int_is_odd(TEMP(3))) { - if((res = mp_int_add(TEMP(2), TEMP(7), TEMP(2))) != MP_OK) - goto CLEANUP; - if((res = mp_int_sub(TEMP(3), TEMP(6), TEMP(3))) != MP_OK) - goto CLEANUP; - } - - s_qdiv(TEMP(2), 1); - s_qdiv(TEMP(3), 1); - } - - if(mp_int_compare(TEMP(4), TEMP(5)) >= 0) { - if((res = mp_int_sub(TEMP(4), TEMP(5), TEMP(4))) != MP_OK) goto CLEANUP; - if((res = mp_int_sub(TEMP(0), TEMP(2), TEMP(0))) != MP_OK) goto CLEANUP; - if((res = mp_int_sub(TEMP(1), TEMP(3), TEMP(1))) != MP_OK) goto CLEANUP; - } - else { - if((res = mp_int_sub(TEMP(5), TEMP(4), TEMP(5))) != MP_OK) goto CLEANUP; - if((res = mp_int_sub(TEMP(2), TEMP(0), TEMP(2))) != MP_OK) goto CLEANUP; - if((res = mp_int_sub(TEMP(3), TEMP(1), TEMP(3))) != MP_OK) goto CLEANUP; - } - - if(CMPZ(TEMP(4)) == 0) { - if(x && (res = mp_int_copy(TEMP(2), x)) != MP_OK) goto CLEANUP; - if(y && (res = mp_int_copy(TEMP(3), y)) != MP_OK) goto CLEANUP; - if(c) { - if(!s_qmul(TEMP(5), k)) { - res = MP_MEMORY; - goto CLEANUP; - } - - res = mp_int_copy(TEMP(5), c); - } - - break; - } - } - - CLEANUP: - while(--last >= 0) - mp_int_clear(TEMP(last)); - - return res; -} - -/* }}} */ - -/* {{{ mp_int_lcm(a, b, c) */ - -mp_result mp_int_lcm(mp_int a, mp_int b, mp_int c) -{ - mpz_t lcm; - mp_result res; - - CHECK(a != NULL && b != NULL && c != NULL); - - /* Since a * b = gcd(a, b) * lcm(a, b), we can compute - lcm(a, b) = (a / gcd(a, b)) * b. - - This formulation insures everything works even if the input - variables share space. - */ - if((res = mp_int_init(&lcm)) != MP_OK) - return res; - if((res = mp_int_gcd(a, b, &lcm)) != MP_OK) - goto CLEANUP; - if((res = mp_int_div(a, &lcm, &lcm, NULL)) != MP_OK) - goto CLEANUP; - if((res = mp_int_mul(&lcm, b, &lcm)) != MP_OK) - goto CLEANUP; - - res = mp_int_copy(&lcm, c); - - CLEANUP: - mp_int_clear(&lcm); - - return res; -} - -/* }}} */ - -/* {{{ mp_int_divisible_value(a, v) */ - -int mp_int_divisible_value(mp_int a, mp_small v) -{ - mp_small rem = 0; - - if(mp_int_div_value(a, v, NULL, &rem) != MP_OK) - return 0; - - return rem == 0; -} - -/* }}} */ - -/* {{{ mp_int_is_pow2(z) */ - -int mp_int_is_pow2(mp_int z) -{ - CHECK(z != NULL); - - return s_isp2(z); -} - -/* }}} */ - -/* {{{ mp_int_root(a, b, c) */ - -/* Implementation of Newton's root finding method, based loosely on a - patch contributed by Hal Finkel - modified by M. J. Fromberger. - */ -mp_result mp_int_root(mp_int a, mp_small b, mp_int c) -{ - mp_result res = MP_OK; - mpz_t temp[5]; - int last = 0; - int flips = 0; - - CHECK(a != NULL && c != NULL && b > 0); - - if(b == 1) { - return mp_int_copy(a, c); - } - if(MP_SIGN(a) == MP_NEG) { - if(b % 2 == 0) - return MP_UNDEF; /* root does not exist for negative a with even b */ - else - flips = 1; - } - - SETUP(mp_int_init_copy(TEMP(last), a), last); - SETUP(mp_int_init_copy(TEMP(last), a), last); - SETUP(mp_int_init(TEMP(last)), last); - SETUP(mp_int_init(TEMP(last)), last); - SETUP(mp_int_init(TEMP(last)), last); - - (void) mp_int_abs(TEMP(0), TEMP(0)); - (void) mp_int_abs(TEMP(1), TEMP(1)); - - for(;;) { - if((res = mp_int_expt(TEMP(1), b, TEMP(2))) != MP_OK) - goto CLEANUP; - - if(mp_int_compare_unsigned(TEMP(2), TEMP(0)) <= 0) - break; - - if((res = mp_int_sub(TEMP(2), TEMP(0), TEMP(2))) != MP_OK) - goto CLEANUP; - if((res = mp_int_expt(TEMP(1), b - 1, TEMP(3))) != MP_OK) - goto CLEANUP; - if((res = mp_int_mul_value(TEMP(3), b, TEMP(3))) != MP_OK) - goto CLEANUP; - if((res = mp_int_div(TEMP(2), TEMP(3), TEMP(4), NULL)) != MP_OK) - goto CLEANUP; - if((res = mp_int_sub(TEMP(1), TEMP(4), TEMP(4))) != MP_OK) - goto CLEANUP; - - if(mp_int_compare_unsigned(TEMP(1), TEMP(4)) == 0) { - if((res = mp_int_sub_value(TEMP(4), 1, TEMP(4))) != MP_OK) - goto CLEANUP; - } - if((res = mp_int_copy(TEMP(4), TEMP(1))) != MP_OK) - goto CLEANUP; - } - - if((res = mp_int_copy(TEMP(1), c)) != MP_OK) - goto CLEANUP; - - /* If the original value of a was negative, flip the output sign. */ - if(flips) - (void) mp_int_neg(c, c); /* cannot fail */ - - CLEANUP: - while(--last >= 0) - mp_int_clear(TEMP(last)); - - return res; -} - -/* }}} */ - -/* {{{ mp_int_to_int(z, out) */ - -mp_result mp_int_to_int(mp_int z, mp_small *out) -{ - mp_usmall uv = 0; - mp_size uz; - mp_digit *dz; - mp_sign sz; - - CHECK(z != NULL); - - /* Make sure the value is representable as an int */ - sz = MP_SIGN(z); - if((sz == MP_ZPOS && mp_int_compare_value(z, MP_SMALL_MAX) > 0) || - mp_int_compare_value(z, MP_SMALL_MIN) < 0) - return MP_RANGE; - - uz = MP_USED(z); - dz = MP_DIGITS(z) + uz - 1; - - while(uz > 0) { - uv <<= MP_DIGIT_BIT/2; - uv = (uv << (MP_DIGIT_BIT/2)) | *dz--; - --uz; - } - - if(out) - *out = (sz == MP_NEG) ? -(mp_small)uv : (mp_small)uv; - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_to_uint(z, *out) */ - -mp_result mp_int_to_uint(mp_int z, mp_usmall *out) -{ - mp_usmall uv = 0; - mp_size uz; - mp_digit *dz; - mp_sign sz; - - CHECK(z != NULL); - - /* Make sure the value is representable as an int */ - sz = MP_SIGN(z); - if(!(sz == MP_ZPOS && mp_int_compare_value(z, UINT_MAX) <= 0)) - return MP_RANGE; - - uz = MP_USED(z); - dz = MP_DIGITS(z) + uz - 1; - - while(uz > 0) { - uv <<= MP_DIGIT_BIT/2; - uv = (uv << (MP_DIGIT_BIT/2)) | *dz--; - --uz; - } - - if(out) - *out = uv; - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_to_string(z, radix, str, limit) */ - -mp_result mp_int_to_string(mp_int z, mp_size radix, - char *str, int limit) -{ - mp_result res; - int cmp = 0; - - CHECK(z != NULL && str != NULL && limit >= 2); - - if(radix < MP_MIN_RADIX || radix > MP_MAX_RADIX) - return MP_RANGE; - - if(CMPZ(z) == 0) { - *str++ = s_val2ch(0, 1); - } - else { - mpz_t tmp; - char *h, *t; - - if((res = mp_int_init_copy(&tmp, z)) != MP_OK) - return res; - - if(MP_SIGN(z) == MP_NEG) { - *str++ = '-'; - --limit; - } - h = str; - - /* Generate digits in reverse order until finished or limit reached */ - for(/* */; limit > 0; --limit) { - mp_digit d; - - if((cmp = CMPZ(&tmp)) == 0) - break; - - d = s_ddiv(&tmp, (mp_digit)radix); - *str++ = s_val2ch(d, 1); - } - t = str - 1; - - /* Put digits back in correct output order */ - while(h < t) { - char tc = *h; - *h++ = *t; - *t-- = tc; - } - - mp_int_clear(&tmp); - } - - *str = '\0'; - if(cmp == 0) - return MP_OK; - else - return MP_TRUNC; -} - -/* }}} */ - -/* {{{ mp_int_string_len(z, radix) */ - -mp_result mp_int_string_len(mp_int z, mp_size radix) -{ - int len; - - CHECK(z != NULL); - - if(radix < MP_MIN_RADIX || radix > MP_MAX_RADIX) - return MP_RANGE; - - len = s_outlen(z, radix) + 1; /* for terminator */ - - /* Allow for sign marker on negatives */ - if(MP_SIGN(z) == MP_NEG) - len += 1; - - return len; -} - -/* }}} */ - -/* {{{ mp_int_read_string(z, radix, *str) */ - -/* Read zero-terminated string into z */ -mp_result mp_int_read_string(mp_int z, mp_size radix, const char *str) -{ - return mp_int_read_cstring(z, radix, str, NULL); - -} - -/* }}} */ - -/* {{{ mp_int_read_cstring(z, radix, *str, **end) */ - -mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end) -{ - int ch; - - CHECK(z != NULL && str != NULL); - - if(radix < MP_MIN_RADIX || radix > MP_MAX_RADIX) - return MP_RANGE; - - /* Skip leading whitespace */ - while(isspace((int)*str)) - ++str; - - /* Handle leading sign tag (+/-, positive default) */ - switch(*str) { - case '-': - MP_SIGN(z) = MP_NEG; - ++str; - break; - case '+': - ++str; /* fallthrough */ - default: - MP_SIGN(z) = MP_ZPOS; - break; - } - - /* Skip leading zeroes */ - while((ch = s_ch2val(*str, radix)) == 0) - ++str; - - /* Make sure there is enough space for the value */ - if(!s_pad(z, s_inlen(strlen(str), radix))) - return MP_MEMORY; - - MP_USED(z) = 1; z->digits[0] = 0; - - while(*str != '\0' && ((ch = s_ch2val(*str, radix)) >= 0)) { - s_dmul(z, (mp_digit)radix); - s_dadd(z, (mp_digit)ch); - ++str; - } - - CLAMP(z); - - /* Override sign for zero, even if negative specified. */ - if(CMPZ(z) == 0) - MP_SIGN(z) = MP_ZPOS; - - if(end != NULL) - *end = (char *)str; - - /* Return a truncation error if the string has unprocessed - characters remaining, so the caller can tell if the whole string - was done */ - if(*str != '\0') - return MP_TRUNC; - else - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_count_bits(z) */ - -mp_result mp_int_count_bits(mp_int z) -{ - mp_size nbits = 0, uz; - mp_digit d; - - CHECK(z != NULL); - - uz = MP_USED(z); - if(uz == 1 && z->digits[0] == 0) - return 1; - - --uz; - nbits = uz * MP_DIGIT_BIT; - d = z->digits[uz]; - - while(d != 0) { - d >>= 1; - ++nbits; - } - - return nbits; -} - -/* }}} */ - -/* {{{ mp_int_to_binary(z, buf, limit) */ - -mp_result mp_int_to_binary(mp_int z, unsigned char *buf, int limit) -{ - static const int PAD_FOR_2C = 1; - - mp_result res; - int limpos = limit; - - CHECK(z != NULL && buf != NULL); - - res = s_tobin(z, buf, &limpos, PAD_FOR_2C); - - if(MP_SIGN(z) == MP_NEG) - s_2comp(buf, limpos); - - return res; -} - -/* }}} */ - -/* {{{ mp_int_read_binary(z, buf, len) */ - -mp_result mp_int_read_binary(mp_int z, unsigned char *buf, int len) -{ - mp_size need, i; - unsigned char *tmp; - mp_digit *dz; - - CHECK(z != NULL && buf != NULL && len > 0); - - /* Figure out how many digits are needed to represent this value */ - need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT; - if(!s_pad(z, need)) - return MP_MEMORY; - - mp_int_zero(z); - - /* If the high-order bit is set, take the 2's complement before - reading the value (it will be restored afterward) */ - if(buf[0] >> (CHAR_BIT - 1)) { - MP_SIGN(z) = MP_NEG; - s_2comp(buf, len); - } - - dz = MP_DIGITS(z); - for(tmp = buf, i = len; i > 0; --i, ++tmp) { - s_qmul(z, (mp_size) CHAR_BIT); - *dz |= *tmp; - } - - /* Restore 2's complement if we took it before */ - if(MP_SIGN(z) == MP_NEG) - s_2comp(buf, len); - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_binary_len(z) */ - -mp_result mp_int_binary_len(mp_int z) -{ - mp_result res = mp_int_count_bits(z); - int bytes; - - if(res <= 0) - return res; - - bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT; - - /* If the highest-order bit falls exactly on a byte boundary, we - need to pad with an extra byte so that the sign will be read - correctly when reading it back in. */ - if(bytes * CHAR_BIT == res) - ++bytes; - - return bytes; -} - -/* }}} */ - -/* {{{ mp_int_to_unsigned(z, buf, limit) */ - -mp_result mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit) -{ - static const int NO_PADDING = 0; - - CHECK(z != NULL && buf != NULL); - - return s_tobin(z, buf, &limit, NO_PADDING); -} - -/* }}} */ - -/* {{{ mp_int_read_unsigned(z, buf, len) */ - -mp_result mp_int_read_unsigned(mp_int z, unsigned char *buf, int len) -{ - mp_size need, i; - unsigned char *tmp; - mp_digit *dz; - - CHECK(z != NULL && buf != NULL && len > 0); - - /* Figure out how many digits are needed to represent this value */ - need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT; - if(!s_pad(z, need)) - return MP_MEMORY; - - mp_int_zero(z); - - dz = MP_DIGITS(z); - for(tmp = buf, i = len; i > 0; --i, ++tmp) { - (void) s_qmul(z, CHAR_BIT); - *dz |= *tmp; - } - - return MP_OK; -} - -/* }}} */ - -/* {{{ mp_int_unsigned_len(z) */ - -mp_result mp_int_unsigned_len(mp_int z) -{ - mp_result res = mp_int_count_bits(z); - int bytes; - - if(res <= 0) - return res; - - bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT; - - return bytes; -} - -/* }}} */ - -/* {{{ mp_error_string(res) */ - -const char *mp_error_string(mp_result res) -{ - int ix; - if(res > 0) - return s_unknown_err; - - res = -res; - for(ix = 0; ix < res && s_error_msg[ix] != NULL; ++ix) - ; - - if(s_error_msg[ix] != NULL) - return s_error_msg[ix]; - else - return s_unknown_err; -} - -/* }}} */ - -/*------------------------------------------------------------------------*/ -/* Private functions for internal use. These make assumptions. */ - -/* {{{ s_alloc(num) */ - -STATIC mp_digit *s_alloc(mp_size num) -{ - mp_digit *out = malloc(num * sizeof(mp_digit)); - - assert(out != NULL); /* for debugging */ -#if DEBUG > 1 - { - mp_digit v = (mp_digit) 0xdeadbeef; - int ix; - - for(ix = 0; ix < num; ++ix) - out[ix] = v; - } -#endif - - return out; -} - -/* }}} */ - -/* {{{ s_realloc(old, osize, nsize) */ - -STATIC mp_digit *s_realloc(mp_digit *old, mp_size osize, mp_size nsize) -{ -#if DEBUG > 1 - mp_digit *new = s_alloc(nsize); - int ix; - - for(ix = 0; ix < nsize; ++ix) - new[ix] = (mp_digit) 0xdeadbeef; - - memcpy(new, old, osize * sizeof(mp_digit)); -#else - mp_digit *new = realloc(old, nsize * sizeof(mp_digit)); - - assert(new != NULL); /* for debugging */ -#endif - return new; -} - -/* }}} */ - -/* {{{ s_free(ptr) */ - -STATIC void s_free(void *ptr) -{ - free(ptr); -} - -/* }}} */ - -/* {{{ s_pad(z, min) */ - -STATIC int s_pad(mp_int z, mp_size min) -{ - if(MP_ALLOC(z) < min) { - mp_size nsize = ROUND_PREC(min); - mp_digit *tmp; - - if((void *)z->digits == (void *)z) { - if((tmp = s_alloc(nsize)) == NULL) - return 0; - - COPY(MP_DIGITS(z), tmp, MP_USED(z)); - } - else if((tmp = s_realloc(MP_DIGITS(z), MP_ALLOC(z), nsize)) == NULL) - return 0; - - MP_DIGITS(z) = tmp; - MP_ALLOC(z) = nsize; - } - - return 1; -} - -/* }}} */ - -/* {{{ s_fake(z, value, vbuf) */ - -STATIC void s_fake(mp_int z, mp_small value, mp_digit vbuf[]) -{ - mp_size uv = (mp_size) s_vpack(value, vbuf); - - z->used = uv; - z->alloc = MP_VALUE_DIGITS(value); - z->sign = (value < 0) ? MP_NEG : MP_ZPOS; - z->digits = vbuf; -} - -/* }}} */ - -/* {{{ s_cdig(da, db, len) */ - -STATIC int s_cdig(mp_digit *da, mp_digit *db, mp_size len) -{ - mp_digit *dat = da + len - 1, *dbt = db + len - 1; - - for(/* */; len != 0; --len, --dat, --dbt) { - if(*dat > *dbt) - return 1; - else if(*dat < *dbt) - return -1; - } - - return 0; -} - -/* }}} */ - -/* {{{ s_vpack(v, t[]) */ - -STATIC int s_vpack(mp_small v, mp_digit t[]) -{ - mp_usmall uv = (mp_usmall) ((v < 0) ? -v : v); - int ndig = 0; - - if(uv == 0) - t[ndig++] = 0; - else { - while(uv != 0) { - t[ndig++] = (mp_digit) uv; - uv >>= MP_DIGIT_BIT/2; - uv >>= MP_DIGIT_BIT/2; - } - } - - return ndig; -} - -/* }}} */ - -/* {{{ s_ucmp(a, b) */ - -STATIC int s_ucmp(mp_int a, mp_int b) -{ - mp_size ua = MP_USED(a), ub = MP_USED(b); - - if(ua > ub) - return 1; - else if(ub > ua) - return -1; - else - return s_cdig(MP_DIGITS(a), MP_DIGITS(b), ua); -} - -/* }}} */ - -/* {{{ s_vcmp(a, v) */ - -STATIC int s_vcmp(mp_int a, mp_small v) -{ - mp_digit vdig[MP_VALUE_DIGITS(v)]; - int ndig = 0; - mp_size ua = MP_USED(a); - - ndig = s_vpack(v, vdig); - - if(ua > ndig) - return 1; - else if(ua < ndig) - return -1; - else - return s_cdig(MP_DIGITS(a), vdig, ndig); -} - -/* }}} */ - -/* {{{ s_uadd(da, db, dc, size_a, size_b) */ - -STATIC mp_digit s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc, - mp_size size_a, mp_size size_b) -{ - mp_size pos; - mp_word w = 0; - - /* Insure that da is the longer of the two to simplify later code */ - if(size_b > size_a) { - SWAP(mp_digit *, da, db); - SWAP(mp_size, size_a, size_b); - } - - /* Add corresponding digits until the shorter number runs out */ - for(pos = 0; pos < size_b; ++pos, ++da, ++db, ++dc) { - w = w + (mp_word) *da + (mp_word) *db; - *dc = LOWER_HALF(w); - w = UPPER_HALF(w); - } - - /* Propagate carries as far as necessary */ - for(/* */; pos < size_a; ++pos, ++da, ++dc) { - w = w + *da; - - *dc = LOWER_HALF(w); - w = UPPER_HALF(w); - } - - /* Return carry out */ - return (mp_digit)w; -} - -/* }}} */ - -/* {{{ s_usub(da, db, dc, size_a, size_b) */ - -STATIC void s_usub(mp_digit *da, mp_digit *db, mp_digit *dc, - mp_size size_a, mp_size size_b) -{ - mp_size pos; - mp_word w = 0; - - /* We assume that |a| >= |b| so this should definitely hold */ - assert(size_a >= size_b); - - /* Subtract corresponding digits and propagate borrow */ - for(pos = 0; pos < size_b; ++pos, ++da, ++db, ++dc) { - w = ((mp_word)MP_DIGIT_MAX + 1 + /* MP_RADIX */ - (mp_word)*da) - w - (mp_word)*db; - - *dc = LOWER_HALF(w); - w = (UPPER_HALF(w) == 0); - } - - /* Finish the subtraction for remaining upper digits of da */ - for(/* */; pos < size_a; ++pos, ++da, ++dc) { - w = ((mp_word)MP_DIGIT_MAX + 1 + /* MP_RADIX */ - (mp_word)*da) - w; - - *dc = LOWER_HALF(w); - w = (UPPER_HALF(w) == 0); - } - - /* If there is a borrow out at the end, it violates the precondition */ - assert(w == 0); -} - -/* }}} */ - -/* {{{ s_kmul(da, db, dc, size_a, size_b) */ - -STATIC int s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc, - mp_size size_a, mp_size size_b) -{ - mp_size bot_size; - - /* Make sure b is the smaller of the two input values */ - if(size_b > size_a) { - SWAP(mp_digit *, da, db); - SWAP(mp_size, size_a, size_b); - } - - /* Insure that the bottom is the larger half in an odd-length split; - the code below relies on this being true. - */ - bot_size = (size_a + 1) / 2; - - /* If the values are big enough to bother with recursion, use the - Karatsuba algorithm to compute the product; otherwise use the - normal multiplication algorithm - */ - if(multiply_threshold && - size_a >= multiply_threshold && - size_b > bot_size) { - - mp_digit *t1, *t2, *t3, carry; - - mp_digit *a_top = da + bot_size; - mp_digit *b_top = db + bot_size; - - mp_size at_size = size_a - bot_size; - mp_size bt_size = size_b - bot_size; - mp_size buf_size = 2 * bot_size; - - /* Do a single allocation for all three temporary buffers needed; - each buffer must be big enough to hold the product of two - bottom halves, and one buffer needs space for the completed - product; twice the space is plenty. - */ - if((t1 = s_alloc(4 * buf_size)) == NULL) return 0; - t2 = t1 + buf_size; - t3 = t2 + buf_size; - ZERO(t1, 4 * buf_size); - - /* t1 and t2 are initially used as temporaries to compute the inner product - (a1 + a0)(b1 + b0) = a1b1 + a1b0 + a0b1 + a0b0 - */ - carry = s_uadd(da, a_top, t1, bot_size, at_size); /* t1 = a1 + a0 */ - t1[bot_size] = carry; - - carry = s_uadd(db, b_top, t2, bot_size, bt_size); /* t2 = b1 + b0 */ - t2[bot_size] = carry; - - (void) s_kmul(t1, t2, t3, bot_size + 1, bot_size + 1); /* t3 = t1 * t2 */ - - /* Now we'll get t1 = a0b0 and t2 = a1b1, and subtract them out so that - we're left with only the pieces we want: t3 = a1b0 + a0b1 - */ - ZERO(t1, buf_size); - ZERO(t2, buf_size); - (void) s_kmul(da, db, t1, bot_size, bot_size); /* t1 = a0 * b0 */ - (void) s_kmul(a_top, b_top, t2, at_size, bt_size); /* t2 = a1 * b1 */ - - /* Subtract out t1 and t2 to get the inner product */ - s_usub(t3, t1, t3, buf_size + 2, buf_size); - s_usub(t3, t2, t3, buf_size + 2, buf_size); - - /* Assemble the output value */ - COPY(t1, dc, buf_size); - carry = s_uadd(t3, dc + bot_size, dc + bot_size, - buf_size + 1, buf_size); - assert(carry == 0); - - carry = s_uadd(t2, dc + 2*bot_size, dc + 2*bot_size, - buf_size, buf_size); - assert(carry == 0); - - s_free(t1); /* note t2 and t3 are just internal pointers to t1 */ - } - else { - s_umul(da, db, dc, size_a, size_b); - } - - return 1; -} - -/* }}} */ - -/* {{{ s_umul(da, db, dc, size_a, size_b) */ - -STATIC void s_umul(mp_digit *da, mp_digit *db, mp_digit *dc, - mp_size size_a, mp_size size_b) -{ - mp_size a, b; - mp_word w; - - for(a = 0; a < size_a; ++a, ++dc, ++da) { - mp_digit *dct = dc; - mp_digit *dbt = db; - - if(*da == 0) - continue; - - w = 0; - for(b = 0; b < size_b; ++b, ++dbt, ++dct) { - w = (mp_word)*da * (mp_word)*dbt + w + (mp_word)*dct; - - *dct = LOWER_HALF(w); - w = UPPER_HALF(w); - } - - *dct = (mp_digit)w; - } -} - -/* }}} */ - -/* {{{ s_ksqr(da, dc, size_a) */ - -STATIC int s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a) -{ - if(multiply_threshold && size_a > multiply_threshold) { - mp_size bot_size = (size_a + 1) / 2; - mp_digit *a_top = da + bot_size; - mp_digit *t1, *t2, *t3, carry; - mp_size at_size = size_a - bot_size; - mp_size buf_size = 2 * bot_size; - - if((t1 = s_alloc(4 * buf_size)) == NULL) return 0; - t2 = t1 + buf_size; - t3 = t2 + buf_size; - ZERO(t1, 4 * buf_size); - - (void) s_ksqr(da, t1, bot_size); /* t1 = a0 ^ 2 */ - (void) s_ksqr(a_top, t2, at_size); /* t2 = a1 ^ 2 */ - - (void) s_kmul(da, a_top, t3, bot_size, at_size); /* t3 = a0 * a1 */ - - /* Quick multiply t3 by 2, shifting left (can't overflow) */ - { - int i, top = bot_size + at_size; - mp_word w, save = 0; - - for(i = 0; i < top; ++i) { - w = t3[i]; - w = (w << 1) | save; - t3[i] = LOWER_HALF(w); - save = UPPER_HALF(w); - } - t3[i] = LOWER_HALF(save); - } - - /* Assemble the output value */ - COPY(t1, dc, 2 * bot_size); - carry = s_uadd(t3, dc + bot_size, dc + bot_size, - buf_size + 1, buf_size); - assert(carry == 0); - - carry = s_uadd(t2, dc + 2*bot_size, dc + 2*bot_size, - buf_size, buf_size); - assert(carry == 0); - - s_free(t1); /* note that t2 and t2 are internal pointers only */ - - } - else { - s_usqr(da, dc, size_a); - } - - return 1; -} - -/* }}} */ - -/* {{{ s_usqr(da, dc, size_a) */ - -STATIC void s_usqr(mp_digit *da, mp_digit *dc, mp_size size_a) -{ - mp_size i, j; - mp_word w; - - for(i = 0; i < size_a; ++i, dc += 2, ++da) { - mp_digit *dct = dc, *dat = da; - - if(*da == 0) - continue; - - /* Take care of the first digit, no rollover */ - w = (mp_word)*dat * (mp_word)*dat + (mp_word)*dct; - *dct = LOWER_HALF(w); - w = UPPER_HALF(w); - ++dat; ++dct; - - for(j = i + 1; j < size_a; ++j, ++dat, ++dct) { - mp_word t = (mp_word)*da * (mp_word)*dat; - mp_word u = w + (mp_word)*dct, ov = 0; - - /* Check if doubling t will overflow a word */ - if(HIGH_BIT_SET(t)) - ov = 1; - - w = t + t; - - /* Check if adding u to w will overflow a word */ - if(ADD_WILL_OVERFLOW(w, u)) - ov = 1; - - w += u; - - *dct = LOWER_HALF(w); - w = UPPER_HALF(w); - if(ov) { - w += MP_DIGIT_MAX; /* MP_RADIX */ - ++w; - } - } - - w = w + *dct; - *dct = (mp_digit)w; - while((w = UPPER_HALF(w)) != 0) { - ++dct; w = w + *dct; - *dct = LOWER_HALF(w); - } - - assert(w == 0); - } -} - -/* }}} */ - -/* {{{ s_dadd(a, b) */ - -STATIC void s_dadd(mp_int a, mp_digit b) -{ - mp_word w = 0; - mp_digit *da = MP_DIGITS(a); - mp_size ua = MP_USED(a); - - w = (mp_word)*da + b; - *da++ = LOWER_HALF(w); - w = UPPER_HALF(w); - - for(ua -= 1; ua > 0; --ua, ++da) { - w = (mp_word)*da + w; - - *da = LOWER_HALF(w); - w = UPPER_HALF(w); - } - - if(w) { - *da = (mp_digit)w; - MP_USED(a) += 1; - } -} - -/* }}} */ - -/* {{{ s_dmul(a, b) */ - -STATIC void s_dmul(mp_int a, mp_digit b) -{ - mp_word w = 0; - mp_digit *da = MP_DIGITS(a); - mp_size ua = MP_USED(a); - - while(ua > 0) { - w = (mp_word)*da * b + w; - *da++ = LOWER_HALF(w); - w = UPPER_HALF(w); - --ua; - } - - if(w) { - *da = (mp_digit)w; - MP_USED(a) += 1; - } -} - -/* }}} */ - -/* {{{ s_dbmul(da, b, dc, size_a) */ - -STATIC void s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc, mp_size size_a) -{ - mp_word w = 0; - - while(size_a > 0) { - w = (mp_word)*da++ * (mp_word)b + w; - - *dc++ = LOWER_HALF(w); - w = UPPER_HALF(w); - --size_a; - } - - if(w) - *dc = LOWER_HALF(w); -} - -/* }}} */ - -/* {{{ s_ddiv(da, d, dc, size_a) */ - -STATIC mp_digit s_ddiv(mp_int a, mp_digit b) -{ - mp_word w = 0, qdigit; - mp_size ua = MP_USED(a); - mp_digit *da = MP_DIGITS(a) + ua - 1; - - for(/* */; ua > 0; --ua, --da) { - w = (w << MP_DIGIT_BIT) | *da; - - if(w >= b) { - qdigit = w / b; - w = w % b; - } - else { - qdigit = 0; - } - - *da = (mp_digit)qdigit; - } - - CLAMP(a); - return (mp_digit)w; -} - -/* }}} */ - -/* {{{ s_qdiv(z, p2) */ - -STATIC void s_qdiv(mp_int z, mp_size p2) -{ - mp_size ndig = p2 / MP_DIGIT_BIT, nbits = p2 % MP_DIGIT_BIT; - mp_size uz = MP_USED(z); - - if(ndig) { - mp_size mark; - mp_digit *to, *from; - - if(ndig >= uz) { - mp_int_zero(z); - return; - } - - to = MP_DIGITS(z); from = to + ndig; - - for(mark = ndig; mark < uz; ++mark) - *to++ = *from++; - - MP_USED(z) = uz - ndig; - } - - if(nbits) { - mp_digit d = 0, *dz, save; - mp_size up = MP_DIGIT_BIT - nbits; - - uz = MP_USED(z); - dz = MP_DIGITS(z) + uz - 1; - - for(/* */; uz > 0; --uz, --dz) { - save = *dz; - - *dz = (*dz >> nbits) | (d << up); - d = save; - } - - CLAMP(z); - } - - if(MP_USED(z) == 1 && z->digits[0] == 0) - MP_SIGN(z) = MP_ZPOS; -} - -/* }}} */ - -/* {{{ s_qmod(z, p2) */ - -STATIC void s_qmod(mp_int z, mp_size p2) -{ - mp_size start = p2 / MP_DIGIT_BIT + 1, rest = p2 % MP_DIGIT_BIT; - mp_size uz = MP_USED(z); - mp_digit mask = (1 << rest) - 1; - - if(start <= uz) { - MP_USED(z) = start; - z->digits[start - 1] &= mask; - CLAMP(z); - } -} - -/* }}} */ - -/* {{{ s_qmul(z, p2) */ - -STATIC int s_qmul(mp_int z, mp_size p2) -{ - mp_size uz, need, rest, extra, i; - mp_digit *from, *to, d; - - if(p2 == 0) - return 1; - - uz = MP_USED(z); - need = p2 / MP_DIGIT_BIT; rest = p2 % MP_DIGIT_BIT; - - /* Figure out if we need an extra digit at the top end; this occurs - if the topmost `rest' bits of the high-order digit of z are not - zero, meaning they will be shifted off the end if not preserved */ - extra = 0; - if(rest != 0) { - mp_digit *dz = MP_DIGITS(z) + uz - 1; - - if((*dz >> (MP_DIGIT_BIT - rest)) != 0) - extra = 1; - } - - if(!s_pad(z, uz + need + extra)) - return 0; - - /* If we need to shift by whole digits, do that in one pass, then - to back and shift by partial digits. - */ - if(need > 0) { - from = MP_DIGITS(z) + uz - 1; - to = from + need; - - for(i = 0; i < uz; ++i) - *to-- = *from--; - - ZERO(MP_DIGITS(z), need); - uz += need; - } - - if(rest) { - d = 0; - for(i = need, from = MP_DIGITS(z) + need; i < uz; ++i, ++from) { - mp_digit save = *from; - - *from = (*from << rest) | (d >> (MP_DIGIT_BIT - rest)); - d = save; - } - - d >>= (MP_DIGIT_BIT - rest); - if(d != 0) { - *from = d; - uz += extra; - } - } - - MP_USED(z) = uz; - CLAMP(z); - - return 1; -} - -/* }}} */ - -/* {{{ s_qsub(z, p2) */ - -/* Compute z = 2^p2 - |z|; requires that 2^p2 >= |z| - The sign of the result is always zero/positive. - */ -STATIC int s_qsub(mp_int z, mp_size p2) -{ - mp_digit hi = (1 << (p2 % MP_DIGIT_BIT)), *zp; - mp_size tdig = (p2 / MP_DIGIT_BIT), pos; - mp_word w = 0; - - if(!s_pad(z, tdig + 1)) - return 0; - - for(pos = 0, zp = MP_DIGITS(z); pos < tdig; ++pos, ++zp) { - w = ((mp_word) MP_DIGIT_MAX + 1) - w - (mp_word)*zp; - - *zp = LOWER_HALF(w); - w = UPPER_HALF(w) ? 0 : 1; - } - - w = ((mp_word) MP_DIGIT_MAX + 1 + hi) - w - (mp_word)*zp; - *zp = LOWER_HALF(w); - - assert(UPPER_HALF(w) != 0); /* no borrow out should be possible */ - - MP_SIGN(z) = MP_ZPOS; - CLAMP(z); - - return 1; -} - -/* }}} */ - -/* {{{ s_dp2k(z) */ - -STATIC int s_dp2k(mp_int z) -{ - int k = 0; - mp_digit *dp = MP_DIGITS(z), d; - - if(MP_USED(z) == 1 && *dp == 0) - return 1; - - while(*dp == 0) { - k += MP_DIGIT_BIT; - ++dp; - } - - d = *dp; - while((d & 1) == 0) { - d >>= 1; - ++k; - } - - return k; -} - -/* }}} */ - -/* {{{ s_isp2(z) */ - -STATIC int s_isp2(mp_int z) -{ - mp_size uz = MP_USED(z), k = 0; - mp_digit *dz = MP_DIGITS(z), d; - - while(uz > 1) { - if(*dz++ != 0) - return -1; - k += MP_DIGIT_BIT; - --uz; - } - - d = *dz; - while(d > 1) { - if(d & 1) - return -1; - ++k; d >>= 1; - } - - return (int) k; -} - -/* }}} */ - -/* {{{ s_2expt(z, k) */ - -STATIC int s_2expt(mp_int z, mp_small k) -{ - mp_size ndig, rest; - mp_digit *dz; - - ndig = (k + MP_DIGIT_BIT) / MP_DIGIT_BIT; - rest = k % MP_DIGIT_BIT; - - if(!s_pad(z, ndig)) - return 0; - - dz = MP_DIGITS(z); - ZERO(dz, ndig); - *(dz + ndig - 1) = (1 << rest); - MP_USED(z) = ndig; - - return 1; -} - -/* }}} */ - -/* {{{ s_norm(a, b) */ - -STATIC int s_norm(mp_int a, mp_int b) -{ - mp_digit d = b->digits[MP_USED(b) - 1]; - int k = 0; - - while(d < (mp_digit) (1 << (MP_DIGIT_BIT - 1))) { /* d < (MP_RADIX / 2) */ - d <<= 1; - ++k; - } - - /* These multiplications can't fail */ - if(k != 0) { - (void) s_qmul(a, (mp_size) k); - (void) s_qmul(b, (mp_size) k); - } - - return k; -} - -/* }}} */ - -/* {{{ s_brmu(z, m) */ - -STATIC mp_result s_brmu(mp_int z, mp_int m) -{ - mp_size um = MP_USED(m) * 2; - - if(!s_pad(z, um)) - return MP_MEMORY; - - s_2expt(z, MP_DIGIT_BIT * um); - return mp_int_div(z, m, z, NULL); -} - -/* }}} */ - -/* {{{ s_reduce(x, m, mu, q1, q2) */ - -STATIC int s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2) -{ - mp_size um = MP_USED(m), umb_p1, umb_m1; - - umb_p1 = (um + 1) * MP_DIGIT_BIT; - umb_m1 = (um - 1) * MP_DIGIT_BIT; - - if(mp_int_copy(x, q1) != MP_OK) - return 0; - - /* Compute q2 = floor((floor(x / b^(k-1)) * mu) / b^(k+1)) */ - s_qdiv(q1, umb_m1); - UMUL(q1, mu, q2); - s_qdiv(q2, umb_p1); - - /* Set x = x mod b^(k+1) */ - s_qmod(x, umb_p1); - - /* Now, q is a guess for the quotient a / m. - Compute x - q * m mod b^(k+1), replacing x. This may be off - by a factor of 2m, but no more than that. - */ - UMUL(q2, m, q1); - s_qmod(q1, umb_p1); - (void) mp_int_sub(x, q1, x); /* can't fail */ - - /* The result may be < 0; if it is, add b^(k+1) to pin it in the - proper range. */ - if((CMPZ(x) < 0) && !s_qsub(x, umb_p1)) - return 0; - - /* If x > m, we need to back it off until it is in range. - This will be required at most twice. */ - if(mp_int_compare(x, m) >= 0) { - (void) mp_int_sub(x, m, x); - if(mp_int_compare(x, m) >= 0) - (void) mp_int_sub(x, m, x); - } - - /* At this point, x has been properly reduced. */ - return 1; -} - -/* }}} */ - -/* {{{ s_embar(a, b, m, mu, c) */ - -/* Perform modular exponentiation using Barrett's method, where mu is - the reduction constant for m. Assumes a < m, b > 0. */ -STATIC mp_result s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c) -{ - mp_digit *db, *dbt, umu, d; - mpz_t temp[3]; - mp_result res = 0; - int last = 0; - - umu = MP_USED(mu); db = MP_DIGITS(b); dbt = db + MP_USED(b) - 1; - - while(last < 3) { - SETUP(mp_int_init_size(TEMP(last), 4 * umu), last); - ZERO(MP_DIGITS(TEMP(last - 1)), MP_ALLOC(TEMP(last - 1))); - } - - (void) mp_int_set_value(c, 1); - - /* Take care of low-order digits */ - while(db < dbt) { - int i; - - for(d = *db, i = MP_DIGIT_BIT; i > 0; --i, d >>= 1) { - if(d & 1) { - /* The use of a second temporary avoids allocation */ - UMUL(c, a, TEMP(0)); - if(!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2))) { - res = MP_MEMORY; goto CLEANUP; - } - mp_int_copy(TEMP(0), c); - } - - - USQR(a, TEMP(0)); - assert(MP_SIGN(TEMP(0)) == MP_ZPOS); - if(!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2))) { - res = MP_MEMORY; goto CLEANUP; - } - assert(MP_SIGN(TEMP(0)) == MP_ZPOS); - mp_int_copy(TEMP(0), a); - - - } - - ++db; - } - - /* Take care of highest-order digit */ - d = *dbt; - for(;;) { - if(d & 1) { - UMUL(c, a, TEMP(0)); - if(!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2))) { - res = MP_MEMORY; goto CLEANUP; - } - mp_int_copy(TEMP(0), c); - } - - d >>= 1; - if(!d) break; - - USQR(a, TEMP(0)); - if(!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2))) { - res = MP_MEMORY; goto CLEANUP; - } - (void) mp_int_copy(TEMP(0), a); - } - - CLEANUP: - while(--last >= 0) - mp_int_clear(TEMP(last)); - - return res; -} - -/* }}} */ - -/* {{{ s_udiv(a, b) */ - -/* Precondition: a >= b and b > 0 - Postcondition: a' = a / b, b' = a % b - */ -STATIC mp_result s_udiv(mp_int a, mp_int b) -{ - mpz_t q, r, t; - mp_size ua, ub, qpos = 0; - mp_digit *da, btop; - mp_result res = MP_OK; - int k, skip = 0; - - /* Force signs to positive */ - MP_SIGN(a) = MP_ZPOS; - MP_SIGN(b) = MP_ZPOS; - - /* Normalize, per Knuth */ - k = s_norm(a, b); - - ua = MP_USED(a); ub = MP_USED(b); btop = b->digits[ub - 1]; - if((res = mp_int_init_size(&q, ua)) != MP_OK) return res; - if((res = mp_int_init_size(&t, ua + 1)) != MP_OK) goto CLEANUP; - - da = MP_DIGITS(a); - r.digits = da + ua - 1; /* The contents of r are shared with a */ - r.used = 1; - r.sign = MP_ZPOS; - r.alloc = MP_ALLOC(a); - ZERO(t.digits, t.alloc); - - /* Solve for quotient digits, store in q.digits in reverse order */ - while(r.digits >= da) { - assert(qpos <= q.alloc); - - if(s_ucmp(b, &r) > 0) { - r.digits -= 1; - r.used += 1; - - if(++skip > 1 && qpos > 0) - q.digits[qpos++] = 0; - - CLAMP(&r); - } - else { - mp_word pfx = r.digits[r.used - 1]; - mp_word qdigit; - - if(r.used > 1 && pfx <= btop) { - pfx <<= MP_DIGIT_BIT / 2; - pfx <<= MP_DIGIT_BIT / 2; - pfx |= r.digits[r.used - 2]; - } - - qdigit = pfx / btop; - if(qdigit > MP_DIGIT_MAX) { - qdigit = MP_DIGIT_MAX; - } - - s_dbmul(MP_DIGITS(b), (mp_digit) qdigit, t.digits, ub); - t.used = ub + 1; CLAMP(&t); - while(s_ucmp(&t, &r) > 0) { - --qdigit; - (void) mp_int_sub(&t, b, &t); /* cannot fail */ - } - - s_usub(r.digits, t.digits, r.digits, r.used, t.used); - CLAMP(&r); - - q.digits[qpos++] = (mp_digit) qdigit; - ZERO(t.digits, t.used); - skip = 0; - } - } - - /* Put quotient digits in the correct order, and discard extra zeroes */ - q.used = qpos; - REV(mp_digit, q.digits, qpos); - CLAMP(&q); - - /* Denormalize the remainder */ - CLAMP(a); - if(k != 0) - s_qdiv(a, k); - - mp_int_copy(a, b); /* ok: 0 <= r < b */ - mp_int_copy(&q, a); /* ok: q <= a */ - - mp_int_clear(&t); - CLEANUP: - mp_int_clear(&q); - return res; -} - -/* }}} */ - -/* {{{ s_outlen(z, r) */ - -STATIC int s_outlen(mp_int z, mp_size r) -{ - mp_result bits; - double raw; - - assert(r >= MP_MIN_RADIX && r <= MP_MAX_RADIX); - - bits = mp_int_count_bits(z); - raw = (double)bits * s_log2[r]; - - return (int)(raw + 0.999999); -} - -/* }}} */ - -/* {{{ s_inlen(len, r) */ - -STATIC mp_size s_inlen(int len, mp_size r) -{ - double raw = (double)len / s_log2[r]; - mp_size bits = (mp_size)(raw + 0.5); - - return (mp_size)((bits + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT); -} - -/* }}} */ - -/* {{{ s_ch2val(c, r) */ - -STATIC int s_ch2val(char c, int r) -{ - int out; - - if(isdigit((unsigned char) c)) - out = c - '0'; - else if(r > 10 && isalpha((unsigned char) c)) - out = toupper(c) - 'A' + 10; - else - return -1; - - return (out >= r) ? -1 : out; -} - -/* }}} */ - -/* {{{ s_val2ch(v, caps) */ - -STATIC char s_val2ch(int v, int caps) -{ - assert(v >= 0); - - if(v < 10) - return v + '0'; - else { - char out = (v - 10) + 'a'; - - if(caps) - return toupper(out); - else - return out; - } -} - -/* }}} */ - -/* {{{ s_2comp(buf, len) */ - -STATIC void s_2comp(unsigned char *buf, int len) -{ - int i; - unsigned short s = 1; - - for(i = len - 1; i >= 0; --i) { - unsigned char c = ~buf[i]; - - s = c + s; - c = s & UCHAR_MAX; - s >>= CHAR_BIT; - - buf[i] = c; - } - - /* last carry out is ignored */ -} - -/* }}} */ - -/* {{{ s_tobin(z, buf, *limpos) */ - -STATIC mp_result s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad) -{ - mp_size uz; - mp_digit *dz; - int pos = 0, limit = *limpos; - - uz = MP_USED(z); dz = MP_DIGITS(z); - while(uz > 0 && pos < limit) { - mp_digit d = *dz++; - int i; - - for(i = sizeof(mp_digit); i > 0 && pos < limit; --i) { - buf[pos++] = (unsigned char)d; - d >>= CHAR_BIT; - - /* Don't write leading zeroes */ - if(d == 0 && uz == 1) - i = 0; /* exit loop without signaling truncation */ - } - - /* Detect truncation (loop exited with pos >= limit) */ - if(i > 0) break; - - --uz; - } - - if(pad != 0 && (buf[pos - 1] >> (CHAR_BIT - 1))) { - if(pos < limit) - buf[pos++] = 0; - else - uz = 1; - } - - /* Digits are in reverse order, fix that */ - REV(unsigned char, buf, pos); - - /* Return the number of bytes actually written */ - *limpos = pos; - - return (uz == 0) ? MP_OK : MP_TRUNC; -} - -/* }}} */ - -/* {{{ s_print(tag, z) */ - -#if DEBUG -void s_print(char *tag, mp_int z) -{ - int i; - - fprintf(stderr, "%s: %c ", tag, - (MP_SIGN(z) == MP_NEG) ? '-' : '+'); - - for(i = MP_USED(z) - 1; i >= 0; --i) - fprintf(stderr, "%0*X", (int)(MP_DIGIT_BIT / 4), z->digits[i]); - - fputc('\n', stderr); - -} - -void s_print_buf(char *tag, mp_digit *buf, mp_size num) -{ - int i; - - fprintf(stderr, "%s: ", tag); - - for(i = num - 1; i >= 0; --i) - fprintf(stderr, "%0*X", (int)(MP_DIGIT_BIT / 4), buf[i]); - - fputc('\n', stderr); -} -#endif - -/* }}} */ - -/* HERE THERE BE DRAGONS */ diff --git a/source4/heimdal/lib/hcrypto/imath/imath.h b/source4/heimdal/lib/hcrypto/imath/imath.h deleted file mode 100644 index cb877959e9..0000000000 --- a/source4/heimdal/lib/hcrypto/imath/imath.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - Name: imath.h - Purpose: Arbitrary precision integer arithmetic routines. - Author: M. J. Fromberger - Info: $Id: imath.h 635 2008-01-08 18:19:40Z sting $ - - Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved. - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - -#ifndef IMATH_H_ -#define IMATH_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned char mp_sign; -typedef unsigned int mp_size; -typedef int mp_result; -typedef long mp_small; /* must be a signed type */ -typedef unsigned long mp_usmall; /* must be an unsigned type */ -#ifdef USE_LONG_LONG -typedef unsigned int mp_digit; -typedef unsigned long long mp_word; -#else -typedef unsigned short mp_digit; -typedef unsigned int mp_word; -#endif - -typedef struct mpz { - mp_digit single; - mp_digit *digits; - mp_size alloc; - mp_size used; - mp_sign sign; -} mpz_t, *mp_int; - -#define MP_DIGITS(Z) ((Z)->digits) -#define MP_ALLOC(Z) ((Z)->alloc) -#define MP_USED(Z) ((Z)->used) -#define MP_SIGN(Z) ((Z)->sign) - -extern const mp_result MP_OK; -extern const mp_result MP_FALSE; -extern const mp_result MP_TRUE; -extern const mp_result MP_MEMORY; -extern const mp_result MP_RANGE; -extern const mp_result MP_UNDEF; -extern const mp_result MP_TRUNC; -extern const mp_result MP_BADARG; -extern const mp_result MP_MINERR; - -#define MP_DIGIT_BIT (sizeof(mp_digit) * CHAR_BIT) -#define MP_WORD_BIT (sizeof(mp_word) * CHAR_BIT) -#define MP_SMALL_MIN LONG_MIN -#define MP_SMALL_MAX LONG_MAX -#define MP_USMALL_MIN ULONG_MIN -#define MP_USMALL_MAX ULONG_MAX - -#ifdef USE_LONG_LONG -# ifndef ULONG_LONG_MAX -# ifdef ULLONG_MAX -# define ULONG_LONG_MAX ULLONG_MAX -# else -# error "Maximum value of unsigned long long not defined!" -# endif -# endif -# define MP_DIGIT_MAX (ULONG_MAX * 1ULL) -# define MP_WORD_MAX ULONG_LONG_MAX -#else -# define MP_DIGIT_MAX (USHRT_MAX * 1UL) -# define MP_WORD_MAX (UINT_MAX * 1UL) -#endif - -#define MP_MIN_RADIX 2 -#define MP_MAX_RADIX 36 - -/* Values with fewer than this many significant digits use the - standard multiplication algorithm; otherwise, a recursive algorithm - is used. Choose a value to suit your platform. - */ -#define MP_MULT_THRESH 22 - -#define MP_DEFAULT_PREC 8 /* default memory allocation, in digits */ - -extern const mp_sign MP_NEG; -extern const mp_sign MP_ZPOS; - -#define mp_int_is_odd(Z) ((Z)->digits[0] & 1) -#define mp_int_is_even(Z) !((Z)->digits[0] & 1) - -mp_result mp_int_init(mp_int z); -mp_int mp_int_alloc(void); -mp_result mp_int_init_size(mp_int z, mp_size prec); -mp_result mp_int_init_copy(mp_int z, mp_int old); -mp_result mp_int_init_value(mp_int z, mp_small value); -mp_result mp_int_set_value(mp_int z, mp_small value); -void mp_int_clear(mp_int z); -void mp_int_free(mp_int z); - -mp_result mp_int_copy(mp_int a, mp_int c); /* c = a */ -void mp_int_swap(mp_int a, mp_int c); /* swap a, c */ -void mp_int_zero(mp_int z); /* z = 0 */ -mp_result mp_int_abs(mp_int a, mp_int c); /* c = |a| */ -mp_result mp_int_neg(mp_int a, mp_int c); /* c = -a */ -mp_result mp_int_add(mp_int a, mp_int b, mp_int c); /* c = a + b */ -mp_result mp_int_add_value(mp_int a, mp_small value, mp_int c); -mp_result mp_int_sub(mp_int a, mp_int b, mp_int c); /* c = a - b */ -mp_result mp_int_sub_value(mp_int a, mp_small value, mp_int c); -mp_result mp_int_mul(mp_int a, mp_int b, mp_int c); /* c = a * b */ -mp_result mp_int_mul_value(mp_int a, mp_small value, mp_int c); -mp_result mp_int_mul_pow2(mp_int a, mp_small p2, mp_int c); -mp_result mp_int_sqr(mp_int a, mp_int c); /* c = a * a */ -mp_result mp_int_div(mp_int a, mp_int b, /* q = a / b */ - mp_int q, mp_int r); /* r = a % b */ -mp_result mp_int_div_value(mp_int a, mp_small value, /* q = a / value */ - mp_int q, mp_small *r); /* r = a % value */ -mp_result mp_int_div_pow2(mp_int a, mp_small p2, /* q = a / 2^p2 */ - mp_int q, mp_int r); /* r = q % 2^p2 */ -mp_result mp_int_mod(mp_int a, mp_int m, mp_int c); /* c = a % m */ -#define mp_int_mod_value(A, V, R) mp_int_div_value((A), (V), 0, (R)) -mp_result mp_int_expt(mp_int a, mp_small b, mp_int c); /* c = a^b */ -mp_result mp_int_expt_value(mp_small a, mp_small b, mp_int c); /* c = a^b */ - -int mp_int_compare(mp_int a, mp_int b); /* a <=> b */ -int mp_int_compare_unsigned(mp_int a, mp_int b); /* |a| <=> |b| */ -int mp_int_compare_zero(mp_int z); /* a <=> 0 */ -int mp_int_compare_value(mp_int z, mp_small value); /* a <=> v */ - -/* Returns true if v|a, false otherwise (including errors) */ -int mp_int_divisible_value(mp_int a, mp_small v); - -/* Returns k >= 0 such that z = 2^k, if one exists; otherwise < 0 */ -int mp_int_is_pow2(mp_int z); - -mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m, - mp_int c); /* c = a^b (mod m) */ -mp_result mp_int_exptmod_evalue(mp_int a, mp_small value, - mp_int m, mp_int c); /* c = a^v (mod m) */ -mp_result mp_int_exptmod_bvalue(mp_small value, mp_int b, - mp_int m, mp_int c); /* c = v^b (mod m) */ -mp_result mp_int_exptmod_known(mp_int a, mp_int b, - mp_int m, mp_int mu, - mp_int c); /* c = a^b (mod m) */ -mp_result mp_int_redux_const(mp_int m, mp_int c); - -mp_result mp_int_invmod(mp_int a, mp_int m, mp_int c); /* c = 1/a (mod m) */ - -mp_result mp_int_gcd(mp_int a, mp_int b, mp_int c); /* c = gcd(a, b) */ - -mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c, /* c = gcd(a, b) */ - mp_int x, mp_int y); /* c = ax + by */ - -mp_result mp_int_lcm(mp_int a, mp_int b, mp_int c); /* c = lcm(a, b) */ - -mp_result mp_int_root(mp_int a, mp_small b, mp_int c); /* c = floor(a^{1/b}) */ -#define mp_int_sqrt(a, c) mp_int_root(a, 2, c) /* c = floor(sqrt(a)) */ - -/* Convert to a small int, if representable; else MP_RANGE */ -mp_result mp_int_to_int(mp_int z, mp_small *out); -mp_result mp_int_to_uint(mp_int z, mp_usmall *out); - -/* Convert to nul-terminated string with the specified radix, writing at - most limit characters including the nul terminator */ -mp_result mp_int_to_string(mp_int z, mp_size radix, - char *str, int limit); - -/* Return the number of characters required to represent - z in the given radix. May over-estimate. */ -mp_result mp_int_string_len(mp_int z, mp_size radix); - -/* Read zero-terminated string into z */ -mp_result mp_int_read_string(mp_int z, mp_size radix, const char *str); -mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str, - char **end); - -/* Return the number of significant bits in z */ -mp_result mp_int_count_bits(mp_int z); - -/* Convert z to two's complement binary, writing at most limit bytes */ -mp_result mp_int_to_binary(mp_int z, unsigned char *buf, int limit); - -/* Read a two's complement binary value into z from the given buffer */ -mp_result mp_int_read_binary(mp_int z, unsigned char *buf, int len); - -/* Return the number of bytes required to represent z in binary. */ -mp_result mp_int_binary_len(mp_int z); - -/* Convert z to unsigned binary, writing at most limit bytes */ -mp_result mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit); - -/* Read an unsigned binary value into z from the given buffer */ -mp_result mp_int_read_unsigned(mp_int z, unsigned char *buf, int len); - -/* Return the number of bytes required to represent z as unsigned output */ -mp_result mp_int_unsigned_len(mp_int z); - -/* Return a statically allocated string describing error code res */ -const char *mp_error_string(mp_result res); - -#if DEBUG -void s_print(char *tag, mp_int z); -void s_print_buf(char *tag, mp_digit *buf, mp_size num); -#endif - -#ifdef __cplusplus -} -#endif -#endif /* end IMATH_H_ */ diff --git a/source4/heimdal/lib/hcrypto/imath/iprime.c b/source4/heimdal/lib/hcrypto/imath/iprime.c deleted file mode 100644 index 2bc9e7a6d1..0000000000 --- a/source4/heimdal/lib/hcrypto/imath/iprime.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - Name: iprime.c - Purpose: Pseudoprimality testing routines - Author: M. J. Fromberger - Info: $Id: iprime.c 635 2008-01-08 18:19:40Z sting $ - - Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved. - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - -#include "iprime.h" -#include - -static const int s_ptab[] = { - 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, - 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, - 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, - 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, - 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, - 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, - 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, - 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, - 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, - 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, - 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, - 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, - 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, - 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, - 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, - 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, - 991, 997 -#ifdef IMATH_LARGE_PRIME_TABLE - , 1009, 1013, 1019, 1021, 1031, 1033, - 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, - 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, - 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, - 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, - 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, - 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, - 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, - 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, - 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, - 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, - 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, - 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, - 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, - 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, - 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, - 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, - 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, - 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, - 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, - 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, - 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, - 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, - 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, - 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, - 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, - 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, - 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, - 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, - 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, - 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, - 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, - 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, - 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, - 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, - 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, - 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, - 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, - 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, - 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, - 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, - 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, - 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, - 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, - 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, - 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, - 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, - 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, - 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, - 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, - 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, - 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, - 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, - 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, - 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, - 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, - 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, - 4957, 4967, 4969, 4973, 4987, 4993, 4999 -#endif -}; -static const int s_ptab_size = sizeof(s_ptab)/sizeof(s_ptab[0]); - -/* {{{ mp_int_is_prime(z) */ - -/* Test whether z is likely to be prime: - MP_TRUE means it is probably prime - MP_FALSE means it is definitely composite - */ -mp_result mp_int_is_prime(mp_int z) -{ - int i; - mp_small rem; - mp_result res; - - /* First check for divisibility by small primes; this eliminates a - large number of composite candidates quickly - */ - for(i = 0; i < s_ptab_size; ++i) { - if((res = mp_int_div_value(z, s_ptab[i], NULL, &rem)) != MP_OK) - return res; - - if(rem == 0) - return MP_FALSE; - } - - /* Now try Fermat's test for several prime witnesses (since we now - know from the above that z is not a multiple of any of them) - */ - { - mpz_t tmp; - - if((res = mp_int_init(&tmp)) != MP_OK) return res; - - for(i = 0; i < 10 && i < s_ptab_size; ++i) { - if((res = mp_int_exptmod_bvalue(s_ptab[i], z, z, &tmp)) != MP_OK) - return res; - - if(mp_int_compare_value(&tmp, s_ptab[i]) != 0) { - mp_int_clear(&tmp); - return MP_FALSE; - } - } - - mp_int_clear(&tmp); - } - - return MP_TRUE; -} - -/* }}} */ - -/* {{{ mp_int_find_prime(z) */ - -/* Find the first apparent prime in ascending order from z */ -mp_result mp_int_find_prime(mp_int z) -{ - mp_result res; - - if(mp_int_is_even(z) && ((res = mp_int_add_value(z, 1, z)) != MP_OK)) - return res; - - while((res = mp_int_is_prime(z)) == MP_FALSE) { - if((res = mp_int_add_value(z, 2, z)) != MP_OK) - break; - - } - - return res; -} - -/* }}} */ - -/* Here there be dragons */ diff --git a/source4/heimdal/lib/hcrypto/imath/iprime.h b/source4/heimdal/lib/hcrypto/imath/iprime.h deleted file mode 100644 index 6110dccb55..0000000000 --- a/source4/heimdal/lib/hcrypto/imath/iprime.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Name: iprime.h - Purpose: Pseudoprimality testing routines - Author: M. J. Fromberger - Info: $Id: iprime.h 635 2008-01-08 18:19:40Z sting $ - - Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved. - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - -#ifndef IPRIME_H_ -#define IPRIME_H_ - -#include "imath.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Test whether z is likely to be prime - MP_YES means it is probably prime - MP_NO means it is definitely composite - */ -mp_result mp_int_is_prime(mp_int z); - -/* Find the first apparent prime in ascending order from z */ -mp_result mp_int_find_prime(mp_int z); - -#ifdef __cplusplus -} -#endif -#endif /* IPRIME_H_ */ diff --git a/source4/heimdal/lib/hcrypto/rsa-imath.c b/source4/heimdal/lib/hcrypto/rsa-imath.c deleted file mode 100644 index 23d5352700..0000000000 --- a/source4/heimdal/lib/hcrypto/rsa-imath.c +++ /dev/null @@ -1,688 +0,0 @@ -/* - * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -#include -#include -#include -#include - -#include - -#include - -#ifdef USE_HCRYPTO_IMATH - -#include "imath/imath.h" -#include "imath/iprime.h" - -static void -BN2mpz(mpz_t *s, const BIGNUM *bn) -{ - size_t len; - void *p; - - mp_int_init(s); - - len = BN_num_bytes(bn); - p = malloc(len); - BN_bn2bin(bn, p); - mp_int_read_unsigned(s, p, len); - free(p); -} - -static BIGNUM * -mpz2BN(mpz_t *s) -{ - size_t size; - BIGNUM *bn; - void *p; - - size = mp_int_unsigned_len(s); - p = malloc(size); - if (p == NULL && size != 0) - return NULL; - mp_int_to_unsigned(s, p, size); - - bn = BN_bin2bn(p, size, NULL); - free(p); - return bn; -} - -static int random_num(mp_int, size_t); - -static void -setup_blind(mp_int n, mp_int b, mp_int bi) -{ - mp_int_init(b); - mp_int_init(bi); - random_num(b, mp_int_count_bits(n)); - mp_int_mod(b, n, b); - mp_int_invmod(b, n, bi); -} - -static void -blind(mp_int in, mp_int b, mp_int e, mp_int n) -{ - mpz_t t1; - mp_int_init(&t1); - /* in' = (in * b^e) mod n */ - mp_int_exptmod(b, e, n, &t1); - mp_int_mul(&t1, in, in); - mp_int_mod(in, n, in); - mp_int_clear(&t1); -} - -static void -unblind(mp_int out, mp_int bi, mp_int n) -{ - /* out' = (out * 1/b) mod n */ - mp_int_mul(out, bi, out); - mp_int_mod(out, n, out); -} - -static mp_result -rsa_private_calculate(mp_int in, mp_int p, mp_int q, - mp_int dmp1, mp_int dmq1, mp_int iqmp, - mp_int out) -{ - mpz_t vp, vq, u; - mp_int_init(&vp); mp_int_init(&vq); mp_int_init(&u); - - /* vq = c ^ (d mod (q - 1)) mod q */ - /* vp = c ^ (d mod (p - 1)) mod p */ - mp_int_mod(in, p, &u); - mp_int_exptmod(&u, dmp1, p, &vp); - mp_int_mod(in, q, &u); - mp_int_exptmod(&u, dmq1, q, &vq); - - /* C2 = 1/q mod p (iqmp) */ - /* u = (vp - vq)C2 mod p. */ - mp_int_sub(&vp, &vq, &u); - if (mp_int_compare_zero(&u) < 0) - mp_int_add(&u, p, &u); - mp_int_mul(&u, iqmp, &u); - mp_int_mod(&u, p, &u); - - /* c ^ d mod n = vq + u q */ - mp_int_mul(&u, q, &u); - mp_int_add(&u, &vq, out); - - mp_int_clear(&vp); - mp_int_clear(&vq); - mp_int_clear(&u); - - return MP_OK; -} - -/* - * - */ - -static int -imath_rsa_public_encrypt(int flen, const unsigned char* from, - unsigned char* to, RSA* rsa, int padding) -{ - unsigned char *p, *p0; - mp_result res; - size_t size, padlen; - mpz_t enc, dec, n, e; - - if (padding != RSA_PKCS1_PADDING) - return -1; - - size = RSA_size(rsa); - - if (size < RSA_PKCS1_PADDING_SIZE || size - RSA_PKCS1_PADDING_SIZE < flen) - return -2; - - BN2mpz(&n, rsa->n); - BN2mpz(&e, rsa->e); - - p = p0 = malloc(size - 1); - if (p0 == NULL) { - mp_int_clear(&e); - mp_int_clear(&n); - return -3; - } - - padlen = size - flen - 3; - - *p++ = 2; - if (RAND_bytes(p, padlen) != 1) { - mp_int_clear(&e); - mp_int_clear(&n); - free(p0); - return -4; - } - while(padlen) { - if (*p == 0) - *p = 1; - padlen--; - p++; - } - *p++ = 0; - memcpy(p, from, flen); - p += flen; - assert((p - p0) == size - 1); - - mp_int_init(&enc); - mp_int_init(&dec); - mp_int_read_unsigned(&dec, p0, size - 1); - free(p0); - - res = mp_int_exptmod(&dec, &e, &n, &enc); - - mp_int_clear(&dec); - mp_int_clear(&e); - mp_int_clear(&n); - - if (res != MP_OK) - return -4; - - { - size_t ssize; - ssize = mp_int_unsigned_len(&enc); - assert(size >= ssize); - mp_int_to_unsigned(&enc, to, ssize); - size = ssize; - } - mp_int_clear(&enc); - - return size; -} - -static int -imath_rsa_public_decrypt(int flen, const unsigned char* from, - unsigned char* to, RSA* rsa, int padding) -{ - unsigned char *p; - mp_result res; - size_t size; - mpz_t s, us, n, e; - - if (padding != RSA_PKCS1_PADDING) - return -1; - - if (flen > RSA_size(rsa)) - return -2; - - BN2mpz(&n, rsa->n); - BN2mpz(&e, rsa->e); - -#if 0 - /* Check that the exponent is larger then 3 */ - if (mp_int_compare_value(&e, 3) <= 0) { - mp_int_clear(&n); - mp_int_clear(&e); - return -3; - } -#endif - - mp_int_init(&s); - mp_int_init(&us); - mp_int_read_unsigned(&s, rk_UNCONST(from), flen); - - if (mp_int_compare(&s, &n) >= 0) { - mp_int_clear(&n); - mp_int_clear(&e); - return -4; - } - - res = mp_int_exptmod(&s, &e, &n, &us); - - mp_int_clear(&s); - mp_int_clear(&n); - mp_int_clear(&e); - - if (res != MP_OK) - return -5; - p = to; - - - size = mp_int_unsigned_len(&us); - assert(size <= RSA_size(rsa)); - mp_int_to_unsigned(&us, p, size); - - mp_int_clear(&us); - - /* head zero was skipped by mp_int_to_unsigned */ - if (*p == 0) - return -6; - if (*p != 1) - return -7; - size--; p++; - while (size && *p == 0xff) { - size--; p++; - } - if (size == 0 || *p != 0) - return -8; - size--; p++; - - memmove(to, p, size); - - return size; -} - -static int -imath_rsa_private_encrypt(int flen, const unsigned char* from, - unsigned char* to, RSA* rsa, int padding) -{ - unsigned char *p, *p0; - mp_result res; - int size; - mpz_t in, out, n, e, b, bi; - int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0; - int do_unblind = 0; - - if (padding != RSA_PKCS1_PADDING) - return -1; - - size = RSA_size(rsa); - - if (size < RSA_PKCS1_PADDING_SIZE || size - RSA_PKCS1_PADDING_SIZE < flen) - return -2; - - p0 = p = malloc(size); - *p++ = 0; - *p++ = 1; - memset(p, 0xff, size - flen - 3); - p += size - flen - 3; - *p++ = 0; - memcpy(p, from, flen); - p += flen; - assert((p - p0) == size); - - BN2mpz(&n, rsa->n); - BN2mpz(&e, rsa->e); - - mp_int_init(&in); - mp_int_init(&out); - mp_int_read_unsigned(&in, p0, size); - free(p0); - - if(mp_int_compare_zero(&in) < 0 || - mp_int_compare(&in, &n) >= 0) { - size = -3; - goto out; - } - - if (blinding) { - setup_blind(&n, &b, &bi); - blind(&in, &b, &e, &n); - do_unblind = 1; - } - - if (rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 && rsa->iqmp) { - mpz_t p, q, dmp1, dmq1, iqmp; - - BN2mpz(&p, rsa->p); - BN2mpz(&q, rsa->q); - BN2mpz(&dmp1, rsa->dmp1); - BN2mpz(&dmq1, rsa->dmq1); - BN2mpz(&iqmp, rsa->iqmp); - - res = rsa_private_calculate(&in, &p, &q, &dmp1, &dmq1, &iqmp, &out); - - mp_int_clear(&p); - mp_int_clear(&q); - mp_int_clear(&dmp1); - mp_int_clear(&dmq1); - mp_int_clear(&iqmp); - - if (res != MP_OK) { - size = -4; - goto out; - } - } else { - mpz_t d; - - BN2mpz(&d, rsa->d); - res = mp_int_exptmod(&in, &d, &n, &out); - mp_int_clear(&d); - if (res != MP_OK) { - size = -5; - goto out; - } - } - - if (do_unblind) - unblind(&out, &bi, &n); - - if (size > 0) { - size_t ssize; - ssize = mp_int_unsigned_len(&out); - assert(size >= ssize); - mp_int_to_unsigned(&out, to, size); - size = ssize; - } - - out: - if (do_unblind) { - mp_int_clear(&b); - mp_int_clear(&bi); - } - - mp_int_clear(&e); - mp_int_clear(&n); - mp_int_clear(&in); - mp_int_clear(&out); - - return size; -} - -static int -imath_rsa_private_decrypt(int flen, const unsigned char* from, - unsigned char* to, RSA* rsa, int padding) -{ - unsigned char *ptr; - mp_result res; - int size; - mpz_t in, out, n, e, b, bi; - int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0; - int do_unblind = 0; - - if (padding != RSA_PKCS1_PADDING) - return -1; - - size = RSA_size(rsa); - if (flen > size) - return -2; - - mp_int_init(&in); - mp_int_init(&out); - - BN2mpz(&n, rsa->n); - BN2mpz(&e, rsa->e); - - res = mp_int_read_unsigned(&in, rk_UNCONST(from), flen); - if (res != MP_OK) { - size = -1; - goto out; - } - - if(mp_int_compare_zero(&in) < 0 || - mp_int_compare(&in, &n) >= 0) { - size = -2; - goto out; - } - - if (blinding) { - setup_blind(&n, &b, &bi); - blind(&in, &b, &e, &n); - do_unblind = 1; - } - - if (rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 && rsa->iqmp) { - mpz_t p, q, dmp1, dmq1, iqmp; - - BN2mpz(&p, rsa->p); - BN2mpz(&q, rsa->q); - BN2mpz(&dmp1, rsa->dmp1); - BN2mpz(&dmq1, rsa->dmq1); - BN2mpz(&iqmp, rsa->iqmp); - - res = rsa_private_calculate(&in, &p, &q, &dmp1, &dmq1, &iqmp, &out); - - mp_int_clear(&p); - mp_int_clear(&q); - mp_int_clear(&dmp1); - mp_int_clear(&dmq1); - mp_int_clear(&iqmp); - - if (res != MP_OK) { - size = -3; - goto out; - } - - } else { - mpz_t d; - - if(mp_int_compare_zero(&in) < 0 || - mp_int_compare(&in, &n) >= 0) - return MP_RANGE; - - BN2mpz(&d, rsa->d); - res = mp_int_exptmod(&in, &d, &n, &out); - mp_int_clear(&d); - if (res != MP_OK) { - size = -4; - goto out; - } - } - - if (do_unblind) - unblind(&out, &bi, &n); - - ptr = to; - { - size_t ssize; - ssize = mp_int_unsigned_len(&out); - assert(size >= ssize); - mp_int_to_unsigned(&out, ptr, ssize); - size = ssize; - } - - /* head zero was skipped by mp_int_to_unsigned */ - if (*ptr != 2) { - size = -5; - goto out; - } - size--; ptr++; - while (size && *ptr != 0) { - size--; ptr++; - } - if (size == 0) - return -6; - size--; ptr++; - - memmove(to, ptr, size); - - out: - if (do_unblind) { - mp_int_clear(&b); - mp_int_clear(&bi); - } - - mp_int_clear(&e); - mp_int_clear(&n); - mp_int_clear(&in); - mp_int_clear(&out); - - return size; -} - -static int -random_num(mp_int num, size_t len) -{ - unsigned char *p; - mp_result res; - - len = (len + 7) / 8; - p = malloc(len); - if (p == NULL) - return 1; - if (RAND_bytes(p, len) != 1) { - free(p); - return 1; - } - res = mp_int_read_unsigned(num, p, len); - free(p); - if (res != MP_OK) - return 1; - return 0; -} - -#define CHECK(f, v) if ((f) != (v)) { goto out; } - -static int -imath_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) -{ - mpz_t el, p, q, n, d, dmp1, dmq1, iqmp, t1, t2, t3; - int counter, ret; - - if (bits < 789) - return -1; - - ret = -1; - - mp_int_init(&el); - mp_int_init(&p); - mp_int_init(&q); - mp_int_init(&n); - mp_int_init(&d); - mp_int_init(&dmp1); - mp_int_init(&dmq1); - mp_int_init(&iqmp); - mp_int_init(&t1); - mp_int_init(&t2); - mp_int_init(&t3); - - BN2mpz(&el, e); - - /* generate p and q so that p != q and bits(pq) ~ bits */ - counter = 0; - do { - BN_GENCB_call(cb, 2, counter++); - CHECK(random_num(&p, bits / 2 + 1), 0); - CHECK(mp_int_find_prime(&p), MP_TRUE); - - CHECK(mp_int_sub_value(&p, 1, &t1), MP_OK); - CHECK(mp_int_gcd(&t1, &el, &t2), MP_OK); - } while(mp_int_compare_value(&t2, 1) != 0); - - BN_GENCB_call(cb, 3, 0); - - counter = 0; - do { - BN_GENCB_call(cb, 2, counter++); - CHECK(random_num(&q, bits / 2 + 1), 0); - CHECK(mp_int_find_prime(&q), MP_TRUE); - - if (mp_int_compare(&p, &q) == 0) /* don't let p and q be the same */ - continue; - - CHECK(mp_int_sub_value(&q, 1, &t1), MP_OK); - CHECK(mp_int_gcd(&t1, &el, &t2), MP_OK); - } while(mp_int_compare_value(&t2, 1) != 0); - - /* make p > q */ - if (mp_int_compare(&p, &q) < 0) - mp_int_swap(&p, &q); - - BN_GENCB_call(cb, 3, 1); - - /* calculate n, n = p * q */ - CHECK(mp_int_mul(&p, &q, &n), MP_OK); - - /* calculate d, d = 1/e mod (p - 1)(q - 1) */ - CHECK(mp_int_sub_value(&p, 1, &t1), MP_OK); - CHECK(mp_int_sub_value(&q, 1, &t2), MP_OK); - CHECK(mp_int_mul(&t1, &t2, &t3), MP_OK); - CHECK(mp_int_invmod(&el, &t3, &d), MP_OK); - - /* calculate dmp1 dmp1 = d mod (p-1) */ - CHECK(mp_int_mod(&d, &t1, &dmp1), MP_OK); - /* calculate dmq1 dmq1 = d mod (q-1) */ - CHECK(mp_int_mod(&d, &t2, &dmq1), MP_OK); - /* calculate iqmp iqmp = 1/q mod p */ - CHECK(mp_int_invmod(&q, &p, &iqmp), MP_OK); - - /* fill in RSA key */ - - rsa->e = mpz2BN(&el); - rsa->p = mpz2BN(&p); - rsa->q = mpz2BN(&q); - rsa->n = mpz2BN(&n); - rsa->d = mpz2BN(&d); - rsa->dmp1 = mpz2BN(&dmp1); - rsa->dmq1 = mpz2BN(&dmq1); - rsa->iqmp = mpz2BN(&iqmp); - - ret = 1; -out: - mp_int_clear(&el); - mp_int_clear(&p); - mp_int_clear(&q); - mp_int_clear(&n); - mp_int_clear(&d); - mp_int_clear(&dmp1); - mp_int_clear(&dmq1); - mp_int_clear(&iqmp); - mp_int_clear(&t1); - mp_int_clear(&t2); - mp_int_clear(&t3); - - return ret; -} - -static int -imath_rsa_init(RSA *rsa) -{ - return 1; -} - -static int -imath_rsa_finish(RSA *rsa) -{ - return 1; -} - -const RSA_METHOD hc_rsa_imath_method = { - "hcrypto imath RSA", - imath_rsa_public_encrypt, - imath_rsa_public_decrypt, - imath_rsa_private_encrypt, - imath_rsa_private_decrypt, - NULL, - NULL, - imath_rsa_init, - imath_rsa_finish, - 0, - NULL, - NULL, - NULL, - imath_rsa_generate_key -}; -#endif - -const RSA_METHOD * -RSA_imath_method(void) -{ -#ifdef USE_HCRYPTO_IMATH - return &hc_rsa_imath_method; -#else - return NULL; -#endif -} diff --git a/source4/heimdal/lib/hcrypto/rsa.c b/source4/heimdal/lib/hcrypto/rsa.c index a6e09fe283..235686999e 100644 --- a/source4/heimdal/lib/hcrypto/rsa.c +++ b/source4/heimdal/lib/hcrypto/rsa.c @@ -56,15 +56,17 @@ * Speed for RSA in seconds * no key blinding * 1000 iteration, - * same rsa key + * same rsa keys (1024 and 2048) * operation performed each eteration sign, verify, encrypt, decrypt on a random bit pattern * - * gmp: 0.733615 - * tfm: 2.450173 - * ltm: 3.79 (default in hcrypto) - * openssl: 4.04 - * cdsa: 15.89 - * imath: 40.62 + * name 1024 2048 4098 + * ================================= + * gmp: 0.73 6.60 44.80 + * tfm: 2.45 -- -- + * ltm: 3.79 20.74 105.41 (default in hcrypto) + * openssl: 4.04 11.90 82.59 + * cdsa: 15.89 102.89 721.40 + * imath: 40.62 -- -- * * See the library functions here: @ref hcrypto_rsa */ @@ -516,7 +518,6 @@ RSA_null_method(void) } extern const RSA_METHOD hc_rsa_gmp_method; -extern const RSA_METHOD hc_rsa_imath_method; extern const RSA_METHOD hc_rsa_tfm_method; extern const RSA_METHOD hc_rsa_ltm_method; static const RSA_METHOD *default_rsa_method = &hc_rsa_ltm_method; diff --git a/source4/heimdal/lib/hcrypto/rsa.h b/source4/heimdal/lib/hcrypto/rsa.h index 3fd805fcf0..798852d3f1 100644 --- a/source4/heimdal/lib/hcrypto/rsa.h +++ b/source4/heimdal/lib/hcrypto/rsa.h @@ -40,7 +40,6 @@ /* symbol renaming */ #define RSA_null_method hc_RSA_null_method -#define RSA_imath_method hc_RSA_imath_method #define RSA_ltm_method hc_RSA_ltm_method #define RSA_gmp_method hc_RSA_gmp_method #define RSA_tfm_method hc_RSA_tfm_method @@ -136,7 +135,6 @@ struct RSA { */ const RSA_METHOD *RSA_null_method(void); -const RSA_METHOD *RSA_imath_method(void); const RSA_METHOD *RSA_gmp_method(void); const RSA_METHOD *RSA_tfm_method(void); const RSA_METHOD *RSA_ltm_method(void); diff --git a/source4/heimdal/lib/hcrypto/sha.h b/source4/heimdal/lib/hcrypto/sha.h index a1f5a99318..fbc1810b4a 100644 --- a/source4/heimdal/lib/hcrypto/sha.h +++ b/source4/heimdal/lib/hcrypto/sha.h @@ -43,6 +43,12 @@ #define SHA256_Init hc_SHA256_Init #define SHA256_Update hc_SHA256_Update #define SHA256_Final hc_SHA256_Final +#define SHA384_Init hc_SHA384_Init +#define SHA384_Update hc_SHA384_Update +#define SHA384_Final hc_SHA384_Final +#define SHA512_Init hc_SHA512_Init +#define SHA512_Update hc_SHA512_Update +#define SHA512_Final hc_SHA512_Final /* * SHA-1 diff --git a/source4/heimdal/lib/hcrypto/sha512.c b/source4/heimdal/lib/hcrypto/sha512.c index 18447b6c67..fb38cadb6f 100644 --- a/source4/heimdal/lib/hcrypto/sha512.c +++ b/source4/heimdal/lib/hcrypto/sha512.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Kungliga Tekniska Högskolan + * Copyright (c) 2006, 2010 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -56,26 +56,46 @@ #define H m->counter[7] static const uint64_t constant_512[80] = { - 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, - 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, - 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, - 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, - 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, - 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, - 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, - 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, - 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, - 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, - 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, - 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, - 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, - 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, - 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, - 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, - 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, - 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL }; void @@ -83,14 +103,14 @@ SHA512_Init (SHA512_CTX *m) { m->sz[0] = 0; m->sz[1] = 0; - A = 0x6a09e667f3bcc908; - B = 0xbb67ae8584caa73b; - C = 0x3c6ef372fe94f82b; - D = 0xa54ff53a5f1d36f1; - E = 0x510e527fade682d1; - F = 0x9b05688c2b3e6c1f; - G = 0x1f83d9abfb41bd6b; - H = 0x5be0cd19137e2179; + A = 0x6a09e667f3bcc908ULL; + B = 0xbb67ae8584caa73bULL; + C = 0x3c6ef372fe94f82bULL; + D = 0xa54ff53a5f1d36f1ULL; + E = 0x510e527fade682d1ULL; + F = 0x9b05688c2b3e6c1fULL; + G = 0x1f83d9abfb41bd6bULL; + H = 0x5be0cd19137e2179ULL; } static void @@ -152,17 +172,17 @@ swap_uint64_t (uint64_t t) uint64_t temp; temp = cshift64(t, 32); - temp = ((temp & 0xff00ff00ff00ff00) >> 8) | - ((temp & 0x00ff00ff00ff00ff) << 8); - return ((temp & 0xffff0000ffff0000) >> 16) | - ((temp & 0x0000ffff0000ffff) << 16); + temp = ((temp & 0xff00ff00ff00ff00ULL) >> 8) | + ((temp & 0x00ff00ff00ff00ffULL) << 8); + return ((temp & 0xffff0000ffff0000ULL) >> 16) | + ((temp & 0x0000ffff0000ffffULL) << 16); } -#endif struct x64{ - uint64_t a:64; - uint64_t b:64; + uint64_t a; + uint64_t b; }; +#endif void SHA512_Update (SHA512_CTX *m, const void *v, size_t len) @@ -248,14 +268,14 @@ SHA384_Init(SHA384_CTX *m) { m->sz[0] = 0; m->sz[1] = 0; - A = 0xcbbb9d5dc1059ed8; - B = 0x629a292a367cd507; - C = 0x9159015a3070dd17; - D = 0x152fecd8f70e5939; - E = 0x67332667ffc00b31; - F = 0x8eb44a8768581511; - G = 0xdb0c2e0d64f98fa7; - H = 0x47b5481dbefa4fa4; + A = 0xcbbb9d5dc1059ed8ULL; + B = 0x629a292a367cd507ULL; + C = 0x9159015a3070dd17ULL; + D = 0x152fecd8f70e5939ULL; + E = 0x67332667ffc00b31ULL; + F = 0x8eb44a8768581511ULL; + G = 0xdb0c2e0d64f98fa7ULL; + H = 0x47b5481dbefa4fa4ULL; } void diff --git a/source4/heimdal/lib/hx509/cms.c b/source4/heimdal/lib/hx509/cms.c index 224c39086c..ef986fd4ed 100644 --- a/source4/heimdal/lib/hx509/cms.c +++ b/source4/heimdal/lib/hx509/cms.c @@ -532,6 +532,7 @@ out: * @param flags flags to control the behavior. * - HX509_CMS_EV_NO_KU_CHECK - Dont check KU on certificate * - HX509_CMS_EV_ALLOW_WEAK - Allow weak crytpo + * - HX509_CMS_EV_ID_NAME - prefer issuer name and serial number * @param cert Certificate to encrypt the EnvelopedData encryption key * with. * @param data pointer the data to encrypt. @@ -559,9 +560,9 @@ hx509_cms_envelope_1(hx509_context context, heim_octet_string ivec; heim_octet_string key; hx509_crypto crypto = NULL; + int ret, cmsidflag; EnvelopedData ed; size_t size; - int ret; memset(&ivec, 0, sizeof(ivec)); memset(&key, 0, sizeof(key)); @@ -648,8 +649,15 @@ hx509_cms_envelope_1(hx509_context context, ri = &ed.recipientInfos.val[0]; - ri->version = 0; - ret = fill_CMSIdentifier(cert, CMS_ID_SKI, &ri->rid); + if (flags & HX509_CMS_EV_ID_NAME) { + ri->version = 0; + cmsidflag = CMS_ID_NAME; + } else { + ri->version = 2; + cmsidflag = CMS_ID_SKI; + } + + ret = fill_CMSIdentifier(cert, cmsidflag, &ri->rid); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to set CMS identifier info " diff --git a/source4/heimdal/lib/hx509/collector.c b/source4/heimdal/lib/hx509/collector.c index ab36fe2dc8..1a44de00a3 100644 --- a/source4/heimdal/lib/hx509/collector.c +++ b/source4/heimdal/lib/hx509/collector.c @@ -145,6 +145,7 @@ _hx509_collector_private_key_add(hx509_context context, } else { ret = _hx509_parse_private_key(context, alg, key_data->data, key_data->length, + HX509_KEY_FORMAT_DER, &key->private_key); if (ret) goto out; diff --git a/source4/heimdal/lib/hx509/crypto.c b/source4/heimdal/lib/hx509/crypto.c index de7717af02..a38226d94c 100644 --- a/source4/heimdal/lib/hx509/crypto.c +++ b/source4/heimdal/lib/hx509/crypto.c @@ -53,9 +53,11 @@ struct hx509_private_key_ops { SubjectPublicKeyInfo *); int (*export)(hx509_context context, const hx509_private_key, + hx509_key_format_t, heim_octet_string *); int (*import)(hx509_context, const AlgorithmIdentifier *, - const void *, size_t, hx509_private_key); + const void *, size_t, hx509_key_format_t, + hx509_private_key); int (*generate_private_key)(hx509_context, struct hx509_generate_private_context *, hx509_private_key); @@ -750,18 +752,27 @@ rsa_private_key_import(hx509_context context, const AlgorithmIdentifier *keyai, const void *data, size_t len, + hx509_key_format_t format, hx509_private_key private_key) { - const unsigned char *p = data; + switch (format) { + case HX509_KEY_FORMAT_DER: { + const unsigned char *p = data; + + private_key->private_key.rsa = + d2i_RSAPrivateKey(NULL, &p, len); + if (private_key->private_key.rsa == NULL) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Failed to parse RSA key"); + return HX509_PARSING_KEY_FAILED; + } + private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION; + break; - private_key->private_key.rsa = - d2i_RSAPrivateKey(NULL, &p, len); - if (private_key->private_key.rsa == NULL) { - hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, - "Failed to parse RSA key"); - return HX509_PARSING_KEY_FAILED; } - private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION; + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } return 0; } @@ -812,7 +823,7 @@ rsa_generate_private_key(hx509_context context, unsigned long bits; static const int default_rsa_e = 65537; - static const int default_rsa_bits = 1024; + static const int default_rsa_bits = 2048; private_key->private_key.rsa = RSA_new(); if (private_key->private_key.rsa == NULL) { @@ -828,8 +839,6 @@ rsa_generate_private_key(hx509_context context, if (ctx->num_bits) bits = ctx->num_bits; - else if (ctx->isCA) - bits *= 2; ret = RSA_generate_key_ex(private_key->private_key.rsa, bits, e, NULL); BN_free(e); @@ -846,6 +855,7 @@ rsa_generate_private_key(hx509_context context, static int rsa_private_key_export(hx509_context context, const hx509_private_key key, + hx509_key_format_t format, heim_octet_string *data) { int ret; @@ -853,25 +863,32 @@ rsa_private_key_export(hx509_context context, data->data = NULL; data->length = 0; - ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL); - if (ret <= 0) { - ret = EINVAL; - hx509_set_error_string(context, 0, ret, + switch (format) { + case HX509_KEY_FORMAT_DER: + + ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL); + if (ret <= 0) { + ret = EINVAL; + hx509_set_error_string(context, 0, ret, "Private key is not exportable"); - return ret; - } + return ret; + } - data->data = malloc(ret); - if (data->data == NULL) { - ret = ENOMEM; - hx509_set_error_string(context, 0, ret, "malloc out of memory"); - return ret; - } - data->length = ret; + data->data = malloc(ret); + if (data->data == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "malloc out of memory"); + return ret; + } + data->length = ret; - { - unsigned char *p = data->data; - i2d_RSAPrivateKey(key->private_key.rsa, &p); + { + unsigned char *p = data->data; + i2d_RSAPrivateKey(key->private_key.rsa, &p); + } + break; + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; } return 0; @@ -917,9 +934,10 @@ ecdsa_private_key2SPKI(hx509_context context, static int ecdsa_private_key_export(hx509_context context, const hx509_private_key key, + hx509_key_format_t format, heim_octet_string *data) { - return ENOMEM; + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; } static int @@ -927,6 +945,7 @@ ecdsa_private_key_import(hx509_context context, const AlgorithmIdentifier *keyai, const void *data, size_t len, + hx509_key_format_t format, hx509_private_key private_key) { const unsigned char *p = data; @@ -961,13 +980,21 @@ ecdsa_private_key_import(hx509_context context, pkey = &key; } - private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len); - if (private_key->private_key.ecdsa == NULL) { - hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, - "Failed to parse EC private key"); - return HX509_PARSING_KEY_FAILED; + switch (format) { + case HX509_KEY_FORMAT_DER: + + private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len); + if (private_key->private_key.ecdsa == NULL) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Failed to parse EC private key"); + return HX509_PARSING_KEY_FAILED; + } + private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256; + break; + + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; } - private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256; return 0; } @@ -1735,6 +1762,7 @@ _hx509_parse_private_key(hx509_context context, const AlgorithmIdentifier *keyai, const void *data, size_t len, + hx509_key_format_t format, hx509_private_key *private_key) { struct hx509_private_key_ops *ops; @@ -1754,7 +1782,7 @@ _hx509_parse_private_key(hx509_context context, return ret; } - ret = (*ops->import)(context, keyai, data, len, *private_key); + ret = (*ops->import)(context, keyai, data, len, format, *private_key); if (ret) _hx509_private_key_free(private_key); @@ -2047,13 +2075,14 @@ _hx509_private_key_get_internal(hx509_context context, int _hx509_private_key_export(hx509_context context, const hx509_private_key key, + hx509_key_format_t format, heim_octet_string *data) { if (key->ops->export == NULL) { hx509_clear_error_string(context); return HX509_UNIMPLEMENTED_OPERATION; } - return (*key->ops->export)(context, key, data); + return (*key->ops->export)(context, key, format, data); } /* diff --git a/source4/heimdal/lib/hx509/hx509.h b/source4/heimdal/lib/hx509/hx509.h index b6eeac9d18..1a5e2f3080 100644 --- a/source4/heimdal/lib/hx509/hx509.h +++ b/source4/heimdal/lib/hx509/hx509.h @@ -76,6 +76,13 @@ enum { HX509_CRYPTO_PADDING_NONE = 1 }; +enum { + HX509_KEY_FORMAT_GUESS = 0, + HX509_KEY_FORMAT_DER = 1, + HX509_KEY_FORMAT_WIN_BACKUPKEY = 2 +}; +typedef uint32_t hx509_key_format_t; + struct hx509_cert_attribute_data { heim_oid oid; heim_octet_string data; @@ -135,6 +142,7 @@ typedef enum { /* flags to hx509_cms_envelope_1 */ #define HX509_CMS_EV_NO_KU_CHECK 0x01 #define HX509_CMS_EV_ALLOW_WEAK 0x02 +#define HX509_CMS_EV_ID_NAME 0x04 /* flags to hx509_cms_verify_signed */ #define HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH 0x01 diff --git a/source4/heimdal/lib/hx509/hx509_err.et b/source4/heimdal/lib/hx509/hx509_err.et index 76bbfaeaba..6225f125fb 100644 --- a/source4/heimdal/lib/hx509/hx509_err.et +++ b/source4/heimdal/lib/hx509/hx509_err.et @@ -66,6 +66,7 @@ error_code RSA_PRIVATE_ENCRYPT, "RSA private encyption failed" error_code RSA_PUBLIC_DECRYPT, "RSA public decryption failed" error_code RSA_PRIVATE_DECRYPT, "RSA private decryption failed" error_code ALGORITHM_BEST_BEFORE, "Algorithm has passed its best before date" +error_code KEY_FORMAT_UNSUPPORTED, "Key format is unsupported" # revoke related errors index 96 diff --git a/source4/heimdal/lib/hx509/ks_file.c b/source4/heimdal/lib/hx509/ks_file.c index 645dc405a2..ecd3a6edaa 100644 --- a/source4/heimdal/lib/hx509/ks_file.c +++ b/source4/heimdal/lib/hx509/ks_file.c @@ -541,7 +541,8 @@ store_func(hx509_context context, void *ctx, hx509_cert c) free(data.data); if (_hx509_cert_private_key_exportable(c)) { hx509_private_key key = _hx509_cert_private_key(c); - ret = _hx509_private_key_export(context, key, &data); + ret = _hx509_private_key_export(context, key, + HX509_KEY_FORMAT_DER, &data); if (ret) break; hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f, diff --git a/source4/heimdal/lib/hx509/ks_p12.c b/source4/heimdal/lib/hx509/ks_p12.c index d94ab197cd..704cf071d7 100644 --- a/source4/heimdal/lib/hx509/ks_p12.c +++ b/source4/heimdal/lib/hx509/ks_p12.c @@ -535,6 +535,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c) } ret = _hx509_private_key_export(context, _hx509_cert_private_key(c), + HX509_KEY_FORMAT_DER, &pki.privateKey); if (ret) { free_PKCS8PrivateKeyInfo(&pki); diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index f68ab46cec..100eb1237d 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -317,6 +317,26 @@ kt_ops_copy(krb5_context context, const krb5_context src_context) return 0; } +static const char *sysplugin_dirs[] = { + LIBDIR "/plugin/krb5", +#ifdef __APPLE__ + "/Library/KerberosPlugins/KerberosFrameworkPlugins", + "/System/Library/KerberosPlugins/KerberosFrameworkPlugins", +#endif + NULL +}; + +static void +init_context_once(void *ctx) +{ + krb5_context context = ctx; + + _krb5_load_plugins(context, "krb5", sysplugin_dirs); + + bindtextdomain(HEIMDAL_TEXTDOMAIN, HEIMDAL_LOCALEDIR); +} + + /** * Initializes the context structure and reads the configuration file * /etc/krb5.conf. The structure should be freed by calling @@ -335,15 +355,13 @@ kt_ops_copy(krb5_context context, const krb5_context src_context) KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_init_context(krb5_context *context) { + static heim_base_once_t init_context = HEIM_BASE_ONCE_INIT; krb5_context p; krb5_error_code ret; char **files; *context = NULL; - /* should have a run_once */ - bindtextdomain(HEIMDAL_TEXTDOMAIN, HEIMDAL_LOCALEDIR); - p = calloc(1, sizeof(*p)); if(!p) return ENOMEM; @@ -382,6 +400,8 @@ out: if(ret) { krb5_free_context(p); p = NULL; + } else { + heim_base_once_f(&init_context, p, init_context_once); } *context = p; return ret; diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index d5d9c1d9d5..f0b0692bc0 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -34,1059 +34,29 @@ #define KRB5_DEPRECATED #include "krb5_locl.h" -#include #ifndef HEIMDAL_SMALLER #define DES3_OLD_ENCTYPE 1 #endif -struct key_data { - krb5_keyblock *key; - krb5_data *schedule; -}; - -struct key_usage { - unsigned usage; - struct key_data key; -}; - -struct krb5_crypto_data { - struct encryption_type *et; - struct key_data key; - int num_key_usage; - struct key_usage *key_usage; -}; - -#define CRYPTO_ETYPE(C) ((C)->et->type) - -/* bits for `flags' below */ -#define F_KEYED 1 /* checksum is keyed */ -#define F_CPROOF 2 /* checksum is collision proof */ -#define F_DERIVED 4 /* uses derived keys */ -#define F_VARIANT 8 /* uses `variant' keys (6.4.3) */ -#define F_PSEUDO 16 /* not a real protocol type */ -#define F_SPECIAL 32 /* backwards */ -#define F_DISABLED 64 /* enctype/checksum disabled */ -#define F_WEAK 128 /* enctype is considered weak */ - -struct salt_type { - krb5_salttype type; - const char *name; - krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data, - krb5_salt, krb5_data, krb5_keyblock*); -}; - -struct key_type { - krb5_keytype type; /* XXX */ - const char *name; - size_t bits; - size_t size; - size_t schedule_size; - void (*random_key)(krb5_context, krb5_keyblock*); - void (*schedule)(krb5_context, struct key_type *, struct key_data *); - struct salt_type *string_to_key; - void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t); - void (*cleanup)(krb5_context, struct key_data *); - const EVP_CIPHER *(*evp)(void); -}; - -struct checksum_type { - krb5_cksumtype type; - const char *name; - size_t blocksize; - size_t checksumsize; - unsigned flags; - krb5_error_code (*checksum)(krb5_context context, - struct key_data *key, - const void *buf, size_t len, - unsigned usage, - Checksum *csum); - krb5_error_code (*verify)(krb5_context context, - struct key_data *key, - const void *buf, size_t len, - unsigned usage, - Checksum *csum); -}; - -struct encryption_type { - krb5_enctype type; - const char *name; - size_t blocksize; - size_t padsize; - size_t confoundersize; - struct key_type *keytype; - struct checksum_type *checksum; - struct checksum_type *keyed_checksum; - unsigned flags; - krb5_error_code (*encrypt)(krb5_context context, - struct key_data *key, - void *data, size_t len, - krb5_boolean encryptp, - int usage, - void *ivec); - size_t prf_length; - krb5_error_code (*prf)(krb5_context, - krb5_crypto, const krb5_data *, krb5_data *); -}; - -#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA) -#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55) -#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99) - -static struct checksum_type *_find_checksum(krb5_cksumtype type); -static struct encryption_type *_find_enctype(krb5_enctype type); -static krb5_error_code _get_derived_key(krb5_context, krb5_crypto, - unsigned, struct key_data**); -static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage); -static krb5_error_code derive_key(krb5_context context, - struct encryption_type *et, - struct key_data *key, - const void *constant, - size_t len); -static krb5_error_code hmac(krb5_context context, - struct checksum_type *cm, - const void *data, - size_t len, - unsigned usage, - struct key_data *keyblock, - Checksum *result); -static void free_key_data(krb5_context, - struct key_data *, - struct encryption_type *); -static void free_key_schedule(krb5_context, - struct key_data *, - struct encryption_type *); -static krb5_error_code usage2arcfour (krb5_context, unsigned *); -static void xor (DES_cblock *, const unsigned char *); - -/************************************************************ - * * - ************************************************************/ - -struct evp_schedule { - EVP_CIPHER_CTX ectx; - EVP_CIPHER_CTX dctx; -}; - - -static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER; - -#ifdef HEIM_WEAK_CRYPTO -static void -krb5_DES_random_key(krb5_context context, - krb5_keyblock *key) -{ - DES_cblock *k = key->keyvalue.data; - do { - krb5_generate_random_block(k, sizeof(DES_cblock)); - DES_set_odd_parity(k); - } while(DES_is_weak_key(k)); -} - -static void -krb5_DES_schedule_old(krb5_context context, - struct key_type *kt, - struct key_data *key) -{ - DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data); -} - -#ifdef ENABLE_AFS_STRING_TO_KEY - -/* This defines the Andrew string_to_key function. It accepts a password - * string as input and converts it via a one-way encryption algorithm to a DES - * encryption key. It is compatible with the original Andrew authentication - * service password database. - */ - -/* - * Short passwords, i.e 8 characters or less. - */ -static void -krb5_DES_AFS3_CMU_string_to_key (krb5_data pw, - krb5_data cell, - DES_cblock *key) -{ - char password[8+1]; /* crypt is limited to 8 chars anyway */ - int i; - - for(i = 0; i < 8; i++) { - char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^ - ((i < cell.length) ? - tolower(((unsigned char*)cell.data)[i]) : 0); - password[i] = c ? c : 'X'; - } - password[8] = '\0'; - - memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock)); - - /* parity is inserted into the LSB so left shift each byte up one - bit. This allows ascii characters with a zero MSB to retain as - much significance as possible. */ - for (i = 0; i < sizeof(DES_cblock); i++) - ((unsigned char*)key)[i] <<= 1; - DES_set_odd_parity (key); -} - -/* - * Long passwords, i.e 9 characters or more. - */ -static void -krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw, - krb5_data cell, - DES_cblock *key) -{ - DES_key_schedule schedule; - DES_cblock temp_key; - DES_cblock ivec; - char password[512]; - size_t passlen; - - memcpy(password, pw.data, min(pw.length, sizeof(password))); - if(pw.length < sizeof(password)) { - int len = min(cell.length, sizeof(password) - pw.length); - int i; - - memcpy(password + pw.length, cell.data, len); - for (i = pw.length; i < pw.length + len; ++i) - password[i] = tolower((unsigned char)password[i]); - } - passlen = min(sizeof(password), pw.length + cell.length); - memcpy(&ivec, "kerberos", 8); - memcpy(&temp_key, "kerberos", 8); - DES_set_odd_parity (&temp_key); - DES_set_key_unchecked (&temp_key, &schedule); - DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec); - - memcpy(&temp_key, &ivec, 8); - DES_set_odd_parity (&temp_key); - DES_set_key_unchecked (&temp_key, &schedule); - DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec); - memset(&schedule, 0, sizeof(schedule)); - memset(&temp_key, 0, sizeof(temp_key)); - memset(&ivec, 0, sizeof(ivec)); - memset(password, 0, sizeof(password)); - - DES_set_odd_parity (key); -} - -static krb5_error_code -DES_AFS3_string_to_key(krb5_context context, - krb5_enctype enctype, - krb5_data password, - krb5_salt salt, - krb5_data opaque, - krb5_keyblock *key) -{ - DES_cblock tmp; - if(password.length > 8) - krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp); - else - krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp); - key->keytype = enctype; - krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); - memset(&key, 0, sizeof(key)); - return 0; -} -#endif /* ENABLE_AFS_STRING_TO_KEY */ - -static void -DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key) -{ - DES_key_schedule schedule; - int i; - int reverse = 0; - unsigned char *p; - - unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, - 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; - memset(key, 0, 8); - - p = (unsigned char*)key; - for (i = 0; i < length; i++) { - unsigned char tmp = data[i]; - if (!reverse) - *p++ ^= (tmp << 1); - else - *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4]; - if((i % 8) == 7) - reverse = !reverse; - } - DES_set_odd_parity(key); - if(DES_is_weak_key(key)) - (*key)[7] ^= 0xF0; - DES_set_key_unchecked(key, &schedule); - DES_cbc_cksum((void*)data, key, length, &schedule, key); - memset(&schedule, 0, sizeof(schedule)); - DES_set_odd_parity(key); - if(DES_is_weak_key(key)) - (*key)[7] ^= 0xF0; -} - -static krb5_error_code -krb5_DES_string_to_key(krb5_context context, - krb5_enctype enctype, - krb5_data password, - krb5_salt salt, - krb5_data opaque, - krb5_keyblock *key) -{ - unsigned char *s; - size_t len; - DES_cblock tmp; - -#ifdef ENABLE_AFS_STRING_TO_KEY - if (opaque.length == 1) { - unsigned long v; - _krb5_get_int(opaque.data, &v, 1); - if (v == 1) - return DES_AFS3_string_to_key(context, enctype, password, - salt, opaque, key); - } -#endif - - len = password.length + salt.saltvalue.length; - s = malloc(len); - if(len > 0 && s == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - memcpy(s, password.data, password.length); - memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); - DES_string_to_key_int(s, len, &tmp); - key->keytype = enctype; - krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); - memset(&tmp, 0, sizeof(tmp)); - memset(s, 0, len); - free(s); - return 0; -} - -static void -krb5_DES_random_to_key(krb5_context context, - krb5_keyblock *key, - const void *data, - size_t size) -{ - DES_cblock *k = key->keyvalue.data; - memcpy(k, data, key->keyvalue.length); - DES_set_odd_parity(k); - if(DES_is_weak_key(k)) - xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); -} -#endif - -/* - * - */ - -static void -DES3_random_key(krb5_context context, - krb5_keyblock *key) -{ - DES_cblock *k = key->keyvalue.data; - do { - krb5_generate_random_block(k, 3 * sizeof(DES_cblock)); - DES_set_odd_parity(&k[0]); - DES_set_odd_parity(&k[1]); - DES_set_odd_parity(&k[2]); - } while(DES_is_weak_key(&k[0]) || - DES_is_weak_key(&k[1]) || - DES_is_weak_key(&k[2])); -} - -/* - * A = A xor B. A & B are 8 bytes. - */ - -static void -xor (DES_cblock *key, const unsigned char *b) -{ - unsigned char *a = (unsigned char*)key; - a[0] ^= b[0]; - a[1] ^= b[1]; - a[2] ^= b[2]; - a[3] ^= b[3]; - a[4] ^= b[4]; - a[5] ^= b[5]; - a[6] ^= b[6]; - a[7] ^= b[7]; -} - -#ifdef DES3_OLD_ENCTYPE -static krb5_error_code -DES3_string_to_key(krb5_context context, - krb5_enctype enctype, - krb5_data password, - krb5_salt salt, - krb5_data opaque, - krb5_keyblock *key) -{ - char *str; - size_t len; - unsigned char tmp[24]; - DES_cblock keys[3]; - krb5_error_code ret; - - len = password.length + salt.saltvalue.length; - str = malloc(len); - if(len != 0 && str == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - memcpy(str, password.data, password.length); - memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length); - { - DES_cblock ivec; - DES_key_schedule s[3]; - int i; - - ret = _krb5_n_fold(str, len, tmp, 24); - if (ret) { - memset(str, 0, len); - free(str); - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); - return ret; - } - - for(i = 0; i < 3; i++){ - memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); - DES_set_odd_parity(keys + i); - if(DES_is_weak_key(keys + i)) - xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); - DES_set_key_unchecked(keys + i, &s[i]); - } - memset(&ivec, 0, sizeof(ivec)); - DES_ede3_cbc_encrypt(tmp, - tmp, sizeof(tmp), - &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT); - memset(s, 0, sizeof(s)); - memset(&ivec, 0, sizeof(ivec)); - for(i = 0; i < 3; i++){ - memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); - DES_set_odd_parity(keys + i); - if(DES_is_weak_key(keys + i)) - xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); - } - memset(tmp, 0, sizeof(tmp)); - } - key->keytype = enctype; - krb5_data_copy(&key->keyvalue, keys, sizeof(keys)); - memset(keys, 0, sizeof(keys)); - memset(str, 0, len); - free(str); - return 0; -} -#endif - -static krb5_error_code -DES3_string_to_key_derived(krb5_context context, - krb5_enctype enctype, - krb5_data password, - krb5_salt salt, - krb5_data opaque, - krb5_keyblock *key) -{ - krb5_error_code ret; - size_t len = password.length + salt.saltvalue.length; - char *s; - - s = malloc(len); - if(len != 0 && s == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - memcpy(s, password.data, password.length); - memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); - ret = krb5_string_to_key_derived(context, - s, - len, - enctype, - key); - memset(s, 0, len); - free(s); - return ret; -} - -static void -DES3_random_to_key(krb5_context context, - krb5_keyblock *key, - const void *data, - size_t size) -{ - unsigned char *x = key->keyvalue.data; - const u_char *q = data; - DES_cblock *k; - int i, j; - - memset(x, 0, sizeof(x)); - for (i = 0; i < 3; ++i) { - unsigned char foo; - for (j = 0; j < 7; ++j) { - unsigned char b = q[7 * i + j]; - - x[8 * i + j] = b; - } - foo = 0; - for (j = 6; j >= 0; --j) { - foo |= q[7 * i + j] & 1; - foo <<= 1; - } - x[8 * i + 7] = foo; - } - k = key->keyvalue.data; - for (i = 0; i < 3; i++) { - DES_set_odd_parity(&k[i]); - if(DES_is_weak_key(&k[i])) - xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); - } -} - -/* - * ARCFOUR - */ - -static krb5_error_code -ARCFOUR_string_to_key(krb5_context context, - krb5_enctype enctype, - krb5_data password, - krb5_salt salt, - krb5_data opaque, - krb5_keyblock *key) -{ - krb5_error_code ret; - uint16_t *s = NULL; - size_t len, i; - EVP_MD_CTX *m; - - m = EVP_MD_CTX_create(); - if (m == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); - goto out; - } - - EVP_DigestInit_ex(m, EVP_md4(), NULL); - - ret = wind_utf8ucs2_length(password.data, &len); - if (ret) { - krb5_set_error_message (context, ret, - N_("Password not an UCS2 string", "")); - goto out; - } - - s = malloc (len * sizeof(s[0])); - if (len != 0 && s == NULL) { - krb5_set_error_message (context, ENOMEM, - N_("malloc: out of memory", "")); - ret = ENOMEM; - goto out; - } - - ret = wind_utf8ucs2(password.data, s, &len); - if (ret) { - krb5_set_error_message (context, ret, - N_("Password not an UCS2 string", "")); - goto out; - } - - /* LE encoding */ - for (i = 0; i < len; i++) { - unsigned char p; - p = (s[i] & 0xff); - EVP_DigestUpdate (m, &p, 1); - p = (s[i] >> 8) & 0xff; - EVP_DigestUpdate (m, &p, 1); - } - - key->keytype = enctype; - ret = krb5_data_alloc (&key->keyvalue, 16); - if (ret) { - krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); - goto out; - } - EVP_DigestFinal_ex (m, key->keyvalue.data, NULL); - - out: - EVP_MD_CTX_destroy(m); - if (s) - memset (s, 0, len); - free (s); - return ret; -} - -/* - * AES - */ - -int _krb5_AES_string_to_default_iterator = 4096; - -static krb5_error_code -AES_string_to_key(krb5_context context, - krb5_enctype enctype, - krb5_data password, - krb5_salt salt, - krb5_data opaque, - krb5_keyblock *key) -{ - krb5_error_code ret; - uint32_t iter; - struct encryption_type *et; - struct key_data kd; - - if (opaque.length == 0) - iter = _krb5_AES_string_to_default_iterator; - else if (opaque.length == 4) { - unsigned long v; - _krb5_get_int(opaque.data, &v, 4); - iter = ((uint32_t)v); - } else - return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */ - - et = _find_enctype(enctype); - if (et == NULL) - return KRB5_PROG_KEYTYPE_NOSUPP; - - kd.schedule = NULL; - ALLOC(kd.key, 1); - if(kd.key == NULL) { - krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - kd.key->keytype = enctype; - ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); - if (ret) { - krb5_set_error_message (context, ret, N_("malloc: out of memory", "")); - return ret; - } - - ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length, - salt.saltvalue.data, salt.saltvalue.length, - iter, - et->keytype->size, kd.key->keyvalue.data); - if (ret != 1) { - free_key_data(context, &kd, et); - krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP, - "Error calculating s2k"); - return KRB5_PROG_KEYTYPE_NOSUPP; - } - - ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos")); - if (ret == 0) - ret = krb5_copy_keyblock_contents(context, kd.key, key); - free_key_data(context, &kd, et); - - return ret; -} - -static void -evp_schedule(krb5_context context, struct key_type *kt, struct key_data *kd) -{ - struct evp_schedule *key = kd->schedule->data; - const EVP_CIPHER *c = (*kt->evp)(); - - EVP_CIPHER_CTX_init(&key->ectx); - EVP_CIPHER_CTX_init(&key->dctx); - - EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1); - EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0); -} - -static void -evp_cleanup(krb5_context context, struct key_data *kd) -{ - struct evp_schedule *key = kd->schedule->data; - EVP_CIPHER_CTX_cleanup(&key->ectx); - EVP_CIPHER_CTX_cleanup(&key->dctx); -} - -/* - * - */ - -#ifdef HEIM_WEAK_CRYPTO -static struct salt_type des_salt[] = { - { - KRB5_PW_SALT, - "pw-salt", - krb5_DES_string_to_key - }, -#ifdef ENABLE_AFS_STRING_TO_KEY - { - KRB5_AFS3_SALT, - "afs3-salt", - DES_AFS3_string_to_key - }, -#endif - { 0 } -}; -#endif - -#ifdef DES3_OLD_ENCTYPE -static struct salt_type des3_salt[] = { - { - KRB5_PW_SALT, - "pw-salt", - DES3_string_to_key - }, - { 0 } -}; -#endif - -static struct salt_type des3_salt_derived[] = { - { - KRB5_PW_SALT, - "pw-salt", - DES3_string_to_key_derived - }, - { 0 } -}; - -static struct salt_type AES_salt[] = { - { - KRB5_PW_SALT, - "pw-salt", - AES_string_to_key - }, - { 0 } -}; - -static struct salt_type arcfour_salt[] = { - { - KRB5_PW_SALT, - "pw-salt", - ARCFOUR_string_to_key - }, - { 0 } -}; - -/* - * - */ - -static struct key_type keytype_null = { - KEYTYPE_NULL, - "null", - 0, - 0, - 0, - NULL, - NULL, - NULL -}; - -#ifdef HEIM_WEAK_CRYPTO -static struct key_type keytype_des_old = { - KEYTYPE_DES, - "des-old", - 56, - 8, - sizeof(DES_key_schedule), - krb5_DES_random_key, - krb5_DES_schedule_old, - des_salt, - krb5_DES_random_to_key -}; - -static struct key_type keytype_des = { - KEYTYPE_DES, - "des", - 56, - 8, - sizeof(struct evp_schedule), - krb5_DES_random_key, - evp_schedule, - des_salt, - krb5_DES_random_to_key, - evp_cleanup, - EVP_des_cbc -}; -#endif /* HEIM_WEAK_CRYPTO */ - -#ifdef DES3_OLD_ENCTYPE -static struct key_type keytype_des3 = { - KEYTYPE_DES3, - "des3", - 168, - 24, - sizeof(struct evp_schedule), - DES3_random_key, - evp_schedule, - des3_salt, - DES3_random_to_key, - evp_cleanup, - EVP_des_ede3_cbc -}; -#endif - -static struct key_type keytype_des3_derived = { - KEYTYPE_DES3, - "des3", - 168, - 24, - sizeof(struct evp_schedule), - DES3_random_key, - evp_schedule, - des3_salt_derived, - DES3_random_to_key, - evp_cleanup, - EVP_des_ede3_cbc -}; - -static struct key_type keytype_aes128 = { - KEYTYPE_AES128, - "aes-128", - 128, - 16, - sizeof(struct evp_schedule), - NULL, - evp_schedule, - AES_salt, - NULL, - evp_cleanup, - EVP_aes_128_cbc -}; - -static struct key_type keytype_aes256 = { - KEYTYPE_AES256, - "aes-256", - 256, - 32, - sizeof(struct evp_schedule), - NULL, - evp_schedule, - AES_salt, - NULL, - evp_cleanup, - EVP_aes_256_cbc -}; - -static struct key_type keytype_arcfour = { - KEYTYPE_ARCFOUR, - "arcfour", - 128, - 16, - sizeof(struct evp_schedule), - NULL, - evp_schedule, - arcfour_salt, - NULL, - evp_cleanup, - EVP_rc4 -}; - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_salttype_to_string (krb5_context context, - krb5_enctype etype, - krb5_salttype stype, - char **string) -{ - struct encryption_type *e; - struct salt_type *st; - - e = _find_enctype (etype); - if (e == NULL) { - krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, - "encryption type %d not supported", - etype); - return KRB5_PROG_ETYPE_NOSUPP; - } - for (st = e->keytype->string_to_key; st && st->type; st++) { - if (st->type == stype) { - *string = strdup (st->name); - if (*string == NULL) { - krb5_set_error_message (context, ENOMEM, - N_("malloc: out of memory", "")); - return ENOMEM; - } - return 0; - } - } - krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP, - "salttype %d not supported", stype); - return HEIM_ERR_SALTTYPE_NOSUPP; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_string_to_salttype (krb5_context context, - krb5_enctype etype, - const char *string, - krb5_salttype *salttype) -{ - struct encryption_type *e; - struct salt_type *st; - - e = _find_enctype (etype); - if (e == NULL) { - krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, - N_("encryption type %d not supported", ""), - etype); - return KRB5_PROG_ETYPE_NOSUPP; - } - for (st = e->keytype->string_to_key; st && st->type; st++) { - if (strcasecmp (st->name, string) == 0) { - *salttype = st->type; - return 0; - } - } - krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP, - N_("salttype %s not supported", ""), string); - return HEIM_ERR_SALTTYPE_NOSUPP; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_get_pw_salt(krb5_context context, - krb5_const_principal principal, - krb5_salt *salt) -{ - size_t len; - int i; - krb5_error_code ret; - char *p; - - salt->salttype = KRB5_PW_SALT; - len = strlen(principal->realm); - for (i = 0; i < principal->name.name_string.len; ++i) - len += strlen(principal->name.name_string.val[i]); - ret = krb5_data_alloc (&salt->saltvalue, len); - if (ret) - return ret; - p = salt->saltvalue.data; - memcpy (p, principal->realm, strlen(principal->realm)); - p += strlen(principal->realm); - for (i = 0; i < principal->name.name_string.len; ++i) { - memcpy (p, - principal->name.name_string.val[i], - strlen(principal->name.name_string.val[i])); - p += strlen(principal->name.name_string.val[i]); - } - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_free_salt(krb5_context context, - krb5_salt salt) -{ - krb5_data_free(&salt.saltvalue); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_string_to_key_data (krb5_context context, - krb5_enctype enctype, - krb5_data password, - krb5_principal principal, - krb5_keyblock *key) -{ - krb5_error_code ret; - krb5_salt salt; - - ret = krb5_get_pw_salt(context, principal, &salt); - if(ret) - return ret; - ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key); - krb5_free_salt(context, salt); - return ret; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_string_to_key (krb5_context context, - krb5_enctype enctype, - const char *password, - krb5_principal principal, - krb5_keyblock *key) -{ - krb5_data pw; - pw.data = rk_UNCONST(password); - pw.length = strlen(password); - return krb5_string_to_key_data(context, enctype, pw, principal, key); -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_string_to_key_data_salt (krb5_context context, - krb5_enctype enctype, - krb5_data password, - krb5_salt salt, - krb5_keyblock *key) -{ - krb5_data opaque; - krb5_data_zero(&opaque); - return krb5_string_to_key_data_salt_opaque(context, enctype, password, - salt, opaque, key); -} - -/* - * Do a string -> key for encryption type `enctype' operation on - * `password' (with salt `salt' and the enctype specific data string - * `opaque'), returning the resulting key in `key' - */ - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_string_to_key_data_salt_opaque (krb5_context context, - krb5_enctype enctype, - krb5_data password, - krb5_salt salt, - krb5_data opaque, - krb5_keyblock *key) -{ - struct encryption_type *et =_find_enctype(enctype); - struct salt_type *st; - if(et == NULL) { - krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, - N_("encryption type %d not supported", ""), - enctype); - return KRB5_PROG_ETYPE_NOSUPP; - } - for(st = et->keytype->string_to_key; st && st->type; st++) - if(st->type == salt.salttype) - return (*st->string_to_key)(context, enctype, password, - salt, opaque, key); - krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP, - N_("salt type %d not supported", ""), - salt.salttype); - return HEIM_ERR_SALTTYPE_NOSUPP; -} - -/* - * Do a string -> key for encryption type `enctype' operation on the - * string `password' (with salt `salt'), returning the resulting key - * in `key' - */ +static krb5_error_code _get_derived_key(krb5_context, krb5_crypto, + unsigned, struct key_data**); +static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage); -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_string_to_key_salt (krb5_context context, - krb5_enctype enctype, - const char *password, - krb5_salt salt, - krb5_keyblock *key) -{ - krb5_data pw; - pw.data = rk_UNCONST(password); - pw.length = strlen(password); - return krb5_string_to_key_data_salt(context, enctype, pw, salt, key); -} +static void free_key_schedule(krb5_context, + struct key_data *, + struct encryption_type *); -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_string_to_key_salt_opaque (krb5_context context, - krb5_enctype enctype, - const char *password, - krb5_salt salt, - krb5_data opaque, - krb5_keyblock *key) -{ - krb5_data pw; - pw.data = rk_UNCONST(password); - pw.length = strlen(password); - return krb5_string_to_key_data_salt_opaque(context, enctype, - pw, salt, opaque, key); -} +/************************************************************ + * * + ************************************************************/ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_enctype_keysize(krb5_context context, krb5_enctype type, size_t *keysize) { - struct encryption_type *et = _find_enctype(type); + struct encryption_type *et = _krb5_find_enctype(type); if(et == NULL) { krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, N_("encryption type %d not supported", ""), @@ -1102,7 +72,7 @@ krb5_enctype_keybits(krb5_context context, krb5_enctype type, size_t *keybits) { - struct encryption_type *et = _find_enctype(type); + struct encryption_type *et = _krb5_find_enctype(type); if(et == NULL) { krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, "encryption type %d not supported", @@ -1119,7 +89,7 @@ krb5_generate_random_keyblock(krb5_context context, krb5_keyblock *key) { krb5_error_code ret; - struct encryption_type *et = _find_enctype(type); + struct encryption_type *et = _krb5_find_enctype(type); if(et == NULL) { krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, N_("encryption type %d not supported", ""), @@ -1143,7 +113,7 @@ _key_schedule(krb5_context context, struct key_data *key) { krb5_error_code ret; - struct encryption_type *et = _find_enctype(key->key->keytype); + struct encryption_type *et = _krb5_find_enctype(key->key->keytype); struct key_type *kt; if (et == NULL) { @@ -1178,197 +148,6 @@ _key_schedule(krb5_context context, * * ************************************************************/ -static krb5_error_code -NONE_checksum(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *C) -{ - return 0; -} - -#if defined(DES3_OLD_ENCTYPE) || defined(HEIM_WEAK_CRYPTO) - -static krb5_error_code -des_checksum(krb5_context context, - const EVP_MD *evp_md, - struct key_data *key, - const void *data, - size_t len, - Checksum *cksum) -{ - struct evp_schedule *ctx = key->schedule->data; - EVP_MD_CTX *m; - DES_cblock ivec; - unsigned char *p = cksum->checksum.data; - - krb5_generate_random_block(p, 8); - - m = EVP_MD_CTX_create(); - if (m == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - - EVP_DigestInit_ex(m, evp_md, NULL); - EVP_DigestUpdate(m, p, 8); - EVP_DigestUpdate(m, data, len); - EVP_DigestFinal_ex (m, p + 8, NULL); - EVP_MD_CTX_destroy(m); - memset (&ivec, 0, sizeof(ivec)); - EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1); - EVP_Cipher(&ctx->ectx, p, p, 24); - - return 0; -} - -static krb5_error_code -des_verify(krb5_context context, - const EVP_MD *evp_md, - struct key_data *key, - const void *data, - size_t len, - Checksum *C) -{ - struct evp_schedule *ctx = key->schedule->data; - EVP_MD_CTX *m; - unsigned char tmp[24]; - unsigned char res[16]; - DES_cblock ivec; - krb5_error_code ret = 0; - - m = EVP_MD_CTX_create(); - if (m == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - - memset(&ivec, 0, sizeof(ivec)); - EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1); - EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24); - - EVP_DigestInit_ex(m, evp_md, NULL); - EVP_DigestUpdate(m, tmp, 8); /* confounder */ - EVP_DigestUpdate(m, data, len); - EVP_DigestFinal_ex (m, res, NULL); - EVP_MD_CTX_destroy(m); - if(ct_memcmp(res, tmp + 8, sizeof(res)) != 0) { - krb5_clear_error_message (context); - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; - } - memset(tmp, 0, sizeof(tmp)); - memset(res, 0, sizeof(res)); - return ret; -} - -#endif - -#ifdef HEIM_WEAK_CRYPTO - -static krb5_error_code -CRC32_checksum(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *C) -{ - uint32_t crc; - unsigned char *r = C->checksum.data; - _krb5_crc_init_table (); - crc = _krb5_crc_update (data, len, 0); - r[0] = crc & 0xff; - r[1] = (crc >> 8) & 0xff; - r[2] = (crc >> 16) & 0xff; - r[3] = (crc >> 24) & 0xff; - return 0; -} - -static krb5_error_code -RSA_MD4_checksum(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *C) -{ - if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1) - krb5_abortx(context, "md4 checksum failed"); - return 0; -} - -static krb5_error_code -RSA_MD4_DES_checksum(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *cksum) -{ - return des_checksum(context, EVP_md4(), key, data, len, cksum); -} - -static krb5_error_code -RSA_MD4_DES_verify(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *C) -{ - return des_verify(context, EVP_md5(), key, data, len, C); -} - -static krb5_error_code -RSA_MD5_DES_checksum(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *C) -{ - return des_checksum(context, EVP_md5(), key, data, len, C); -} - -static krb5_error_code -RSA_MD5_DES_verify(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *C) -{ - return des_verify(context, EVP_md5(), key, data, len, C); -} - -#endif /* HEIM_WEAK_CRYPTO */ - -#ifdef DES3_OLD_ENCTYPE -static krb5_error_code -RSA_MD5_DES3_checksum(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *C) -{ - return des_checksum(context, EVP_md5(), key, data, len, C); -} - -static krb5_error_code -RSA_MD5_DES3_verify(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *C) -{ - return des_verify(context, EVP_md5(), key, data, len, C); -} -#endif - static krb5_error_code SHA1_checksum(krb5_context context, struct key_data *key, @@ -1383,14 +162,14 @@ SHA1_checksum(krb5_context context, } /* HMAC according to RFC2104 */ -static krb5_error_code -hmac(krb5_context context, - struct checksum_type *cm, - const void *data, - size_t len, - unsigned usage, - struct key_data *keyblock, - Checksum *result) +krb5_error_code +_krb5_internal_hmac(krb5_context context, + struct checksum_type *cm, + const void *data, + size_t len, + unsigned usage, + struct key_data *keyblock, + Checksum *result) { unsigned char *ipad, *opad; unsigned char *key; @@ -1449,7 +228,7 @@ krb5_hmac(krb5_context context, krb5_keyblock *key, Checksum *result) { - struct checksum_type *c = _find_checksum(cktype); + struct checksum_type *c = _krb5_find_checksum(cktype); struct key_data kd; krb5_error_code ret; @@ -1463,7 +242,7 @@ krb5_hmac(krb5_context context, kd.key = key; kd.schedule = NULL; - ret = hmac(context, c, data, len, usage, &kd, result); + ret = _krb5_internal_hmac(context, c, data, len, usage, &kd, result); if (kd.schedule) krb5_free_data(context, kd.schedule); @@ -1471,15 +250,15 @@ krb5_hmac(krb5_context context, return ret; } -static krb5_error_code -SP_HMAC_SHA1_checksum(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *result) +krb5_error_code +_krb5_SP_HMAC_SHA1_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *result) { - struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1); + struct checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1); Checksum res; char sha1_data[20]; krb5_error_code ret; @@ -1487,257 +266,30 @@ SP_HMAC_SHA1_checksum(krb5_context context, res.checksum.data = sha1_data; res.checksum.length = sizeof(sha1_data); - ret = hmac(context, c, data, len, usage, key, &res); + ret = _krb5_internal_hmac(context, c, data, len, usage, key, &res); if (ret) krb5_abortx(context, "hmac failed"); memcpy(result->checksum.data, res.checksum.data, result->checksum.length); return 0; -} - -/* - * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt - * - * This function made available to PAC routines - */ - -static krb5_error_code -HMAC_MD5_checksum(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *result) -{ - EVP_MD_CTX *m; - struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); - const char signature[] = "signaturekey"; - Checksum ksign_c; - struct key_data ksign; - krb5_keyblock kb; - unsigned char t[4]; - unsigned char tmp[16]; - unsigned char ksign_c_data[16]; - krb5_error_code ret; - - m = EVP_MD_CTX_create(); - if (m == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - ksign_c.checksum.length = sizeof(ksign_c_data); - ksign_c.checksum.data = ksign_c_data; - ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c); - if (ret) { - EVP_MD_CTX_destroy(m); - return ret; - } - ksign.key = &kb; - kb.keyvalue = ksign_c.checksum; - EVP_DigestInit_ex(m, EVP_md5(), NULL); - t[0] = (usage >> 0) & 0xFF; - t[1] = (usage >> 8) & 0xFF; - t[2] = (usage >> 16) & 0xFF; - t[3] = (usage >> 24) & 0xFF; - EVP_DigestUpdate(m, t, 4); - EVP_DigestUpdate(m, data, len); - EVP_DigestFinal_ex (m, tmp, NULL); - EVP_MD_CTX_destroy(m); - - ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result); - if (ret) - return ret; - return 0; -} - -/* HMAC-MD5 checksum over any key (needed for the PAC routines) */ -krb5_error_code -HMAC_MD5_any_checksum(krb5_context context, - const krb5_keyblock *key, - const void *data, - size_t len, - unsigned usage, - Checksum *result) -{ - krb5_error_code ret; - struct key_data local_key; - ret = krb5_copy_keyblock(context, key, &local_key.key); - if (ret) - return ret; - - local_key.schedule = NULL; - ret = krb5_data_alloc (&result->checksum, 16); - if (ret) - return ret; - - result->cksumtype = CKSUMTYPE_HMAC_MD5; - ret = HMAC_MD5_checksum(context, &local_key, data, len, usage, result); - - if (ret) - krb5_data_free(&result->checksum); - - krb5_free_keyblock(context, local_key.key); - return ret; -} - -static struct checksum_type checksum_none = { - CKSUMTYPE_NONE, - "none", - 1, - 0, - 0, - NONE_checksum, - NULL -}; -#ifdef HEIM_WEAK_CRYPTO -static struct checksum_type checksum_crc32 = { - CKSUMTYPE_CRC32, - "crc32", - 1, - 4, - 0, - CRC32_checksum, - NULL -}; -static struct checksum_type checksum_rsa_md4 = { - CKSUMTYPE_RSA_MD4, - "rsa-md4", - 64, - 16, - F_CPROOF, - RSA_MD4_checksum, - NULL -}; -static struct checksum_type checksum_rsa_md4_des = { - CKSUMTYPE_RSA_MD4_DES, - "rsa-md4-des", - 64, - 24, - F_KEYED | F_CPROOF | F_VARIANT, - RSA_MD4_DES_checksum, - RSA_MD4_DES_verify -}; -static struct checksum_type checksum_rsa_md5_des = { - CKSUMTYPE_RSA_MD5_DES, - "rsa-md5-des", - 64, - 24, - F_KEYED | F_CPROOF | F_VARIANT, - RSA_MD5_DES_checksum, - RSA_MD5_DES_verify -}; -#endif /* HEIM_WEAK_CRYPTO */ - -static krb5_error_code -RSA_MD5_checksum(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *C) -{ - if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1) - krb5_abortx(context, "md5 checksum failed"); - return 0; -} - -static struct checksum_type checksum_rsa_md5 = { - CKSUMTYPE_RSA_MD5, - "rsa-md5", - 64, - 16, - F_CPROOF, - RSA_MD5_checksum, - NULL -}; - -#ifdef DES3_OLD_ENCTYPE -static struct checksum_type checksum_rsa_md5_des3 = { - CKSUMTYPE_RSA_MD5_DES3, - "rsa-md5-des3", - 64, - 24, - F_KEYED | F_CPROOF | F_VARIANT, - RSA_MD5_DES3_checksum, - RSA_MD5_DES3_verify -}; -#endif -static struct checksum_type checksum_sha1 = { - CKSUMTYPE_SHA1, - "sha1", - 64, - 20, - F_CPROOF, - SHA1_checksum, - NULL -}; -static struct checksum_type checksum_hmac_sha1_des3 = { - CKSUMTYPE_HMAC_SHA1_DES3, - "hmac-sha1-des3", - 64, - 20, - F_KEYED | F_CPROOF | F_DERIVED, - SP_HMAC_SHA1_checksum, - NULL -}; - -static struct checksum_type checksum_hmac_sha1_aes128 = { - CKSUMTYPE_HMAC_SHA1_96_AES_128, - "hmac-sha1-96-aes128", - 64, - 12, - F_KEYED | F_CPROOF | F_DERIVED, - SP_HMAC_SHA1_checksum, - NULL -}; - -static struct checksum_type checksum_hmac_sha1_aes256 = { - CKSUMTYPE_HMAC_SHA1_96_AES_256, - "hmac-sha1-96-aes256", - 64, - 12, - F_KEYED | F_CPROOF | F_DERIVED, - SP_HMAC_SHA1_checksum, - NULL -}; +} -static struct checksum_type checksum_hmac_md5 = { - CKSUMTYPE_HMAC_MD5, - "hmac-md5", +struct checksum_type _krb5_checksum_sha1 = { + CKSUMTYPE_SHA1, + "sha1", 64, - 16, - F_KEYED | F_CPROOF, - HMAC_MD5_checksum, + 20, + F_CPROOF, + SHA1_checksum, NULL }; -static struct checksum_type *checksum_types[] = { - &checksum_none, -#ifdef HEIM_WEAK_CRYPTO - &checksum_crc32, - &checksum_rsa_md4, - &checksum_rsa_md4_des, - &checksum_rsa_md5_des, -#endif -#ifdef DES3_OLD_ENCTYPE - &checksum_rsa_md5_des3, -#endif - &checksum_rsa_md5, - &checksum_sha1, - &checksum_hmac_sha1_des3, - &checksum_hmac_sha1_aes128, - &checksum_hmac_sha1_aes256, - &checksum_hmac_md5 -}; - -static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]); - -static struct checksum_type * -_find_checksum(krb5_cksumtype type) +struct checksum_type * +_krb5_find_checksum(krb5_cksumtype type) { int i; - for(i = 0; i < num_checksums; i++) - if(checksum_types[i]->type == type) - return checksum_types[i]; + for(i = 0; i < _krb5_num_checksums; i++) + if(_krb5_checksum_types[i]->type == type) + return _krb5_checksum_types[i]; return NULL; } @@ -1832,7 +384,7 @@ krb5_create_checksum(krb5_context context, /* type 0 -> pick from crypto */ if (type) { - ct = _find_checksum(type); + ct = _krb5_find_checksum(type); } else if (crypto) { ct = crypto->et->keyed_checksum; if (ct == NULL) @@ -1848,7 +400,7 @@ krb5_create_checksum(krb5_context context, if (arcfour_checksum_p(ct, crypto)) { keyusage = usage; - usage2arcfour(context, &keyusage); + _krb5_usage2arcfour(context, &keyusage); } else keyusage = CHECKSUM_USAGE(usage); @@ -1870,7 +422,7 @@ verify_checksum(krb5_context context, Checksum c; struct checksum_type *ct; - ct = _find_checksum(cksum->cksumtype); + ct = _krb5_find_checksum(cksum->cksumtype); if (ct == NULL || (ct->flags & F_DISABLED)) { krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, N_("checksum type %d not supported", ""), @@ -1938,9 +490,7 @@ verify_checksum(krb5_context context, return ret; } - if(c.checksum.length != cksum->checksum.length || - ct_memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { - krb5_clear_error_message (context); + if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) { ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; krb5_set_error_message(context, ret, N_("Decrypt integrity check failed for checksum " @@ -1964,7 +514,7 @@ krb5_verify_checksum(krb5_context context, struct checksum_type *ct; unsigned keyusage; - ct = _find_checksum(cksum->cksumtype); + ct = _krb5_find_checksum(cksum->cksumtype); if(ct == NULL) { krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, N_("checksum type %d not supported", ""), @@ -1974,7 +524,7 @@ krb5_verify_checksum(krb5_context context, if (arcfour_checksum_p(ct, crypto)) { keyusage = usage; - usage2arcfour(context, &keyusage); + _krb5_usage2arcfour(context, &keyusage); } else keyusage = CHECKSUM_USAGE(usage); @@ -1992,790 +542,94 @@ krb5_crypto_get_checksum_type(krb5_context context, if (crypto != NULL) { ct = crypto->et->keyed_checksum; if (ct == NULL) - ct = crypto->et->checksum; - } - - if (ct == NULL) { - krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, - N_("checksum type not found", "")); - return KRB5_PROG_SUMTYPE_NOSUPP; - } - - *type = ct->type; - - return 0; -} - - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_checksumsize(krb5_context context, - krb5_cksumtype type, - size_t *size) -{ - struct checksum_type *ct = _find_checksum(type); - if(ct == NULL) { - krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, - N_("checksum type %d not supported", ""), - type); - return KRB5_PROG_SUMTYPE_NOSUPP; - } - *size = ct->checksumsize; - return 0; -} - -KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL -krb5_checksum_is_keyed(krb5_context context, - krb5_cksumtype type) -{ - struct checksum_type *ct = _find_checksum(type); - if(ct == NULL) { - if (context) - krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, - N_("checksum type %d not supported", ""), - type); - return KRB5_PROG_SUMTYPE_NOSUPP; - } - return ct->flags & F_KEYED; -} - -KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL -krb5_checksum_is_collision_proof(krb5_context context, - krb5_cksumtype type) -{ - struct checksum_type *ct = _find_checksum(type); - if(ct == NULL) { - if (context) - krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, - N_("checksum type %d not supported", ""), - type); - return KRB5_PROG_SUMTYPE_NOSUPP; - } - return ct->flags & F_CPROOF; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_checksum_disable(krb5_context context, - krb5_cksumtype type) -{ - struct checksum_type *ct = _find_checksum(type); - if(ct == NULL) { - if (context) - krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, - N_("checksum type %d not supported", ""), - type); - return KRB5_PROG_SUMTYPE_NOSUPP; - } - ct->flags |= F_DISABLED; - return 0; -} - -/************************************************************ - * * - ************************************************************/ - -static krb5_error_code -NULL_encrypt(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ivec) -{ - return 0; -} - -static krb5_error_code -evp_encrypt(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ivec) -{ - struct evp_schedule *ctx = key->schedule->data; - EVP_CIPHER_CTX *c; - c = encryptp ? &ctx->ectx : &ctx->dctx; - if (ivec == NULL) { - /* alloca ? */ - size_t len2 = EVP_CIPHER_CTX_iv_length(c); - void *loiv = malloc(len2); - if (loiv == NULL) { - krb5_clear_error_message(context); - return ENOMEM; - } - memset(loiv, 0, len2); - EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1); - free(loiv); - } else - EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); - EVP_Cipher(c, data, data, len); - return 0; -} - -static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 }; - -static krb5_error_code -evp_encrypt_cts(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ivec) -{ - size_t i, blocksize; - struct evp_schedule *ctx = key->schedule->data; - char tmp[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH]; - EVP_CIPHER_CTX *c; - unsigned char *p; - - c = encryptp ? &ctx->ectx : &ctx->dctx; - - blocksize = EVP_CIPHER_CTX_block_size(c); - - if (len < blocksize) { - krb5_set_error_message(context, EINVAL, - "message block too short"); - return EINVAL; - } else if (len == blocksize) { - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - EVP_Cipher(c, data, data, len); - return 0; - } - - if (ivec) - EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); - else - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - - if (encryptp) { - - p = data; - i = ((len - 1) / blocksize) * blocksize; - EVP_Cipher(c, p, p, i); - p += i - blocksize; - len -= i; - memcpy(ivec2, p, blocksize); - - for (i = 0; i < len; i++) - tmp[i] = p[i + blocksize] ^ ivec2[i]; - for (; i < blocksize; i++) - tmp[i] = 0 ^ ivec2[i]; - - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - EVP_Cipher(c, p, tmp, blocksize); - - memcpy(p + blocksize, ivec2, len); - if (ivec) - memcpy(ivec, p, blocksize); - } else { - char tmp2[EVP_MAX_BLOCK_LENGTH], tmp3[EVP_MAX_BLOCK_LENGTH]; - - p = data; - if (len > blocksize * 2) { - /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */ - i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize); - memcpy(ivec2, p + i - blocksize, blocksize); - EVP_Cipher(c, p, p, i); - p += i; - len -= i + blocksize; - } else { - if (ivec) - memcpy(ivec2, ivec, blocksize); - else - memcpy(ivec2, zero_ivec, blocksize); - len -= blocksize; - } - - memcpy(tmp, p, blocksize); - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - EVP_Cipher(c, tmp2, p, blocksize); - - memcpy(tmp3, p + blocksize, len); - memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */ - - for (i = 0; i < len; i++) - p[i + blocksize] = tmp2[i] ^ tmp3[i]; - - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - EVP_Cipher(c, p, tmp3, blocksize); - - for (i = 0; i < blocksize; i++) - p[i] ^= ivec2[i]; - if (ivec) - memcpy(ivec, tmp, blocksize); - } - return 0; -} - -#ifdef HEIM_WEAK_CRYPTO -static krb5_error_code -evp_des_encrypt_null_ivec(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ignore_ivec) -{ - struct evp_schedule *ctx = key->schedule->data; - EVP_CIPHER_CTX *c; - DES_cblock ivec; - memset(&ivec, 0, sizeof(ivec)); - c = encryptp ? &ctx->ectx : &ctx->dctx; - EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1); - EVP_Cipher(c, data, data, len); - return 0; -} - -static krb5_error_code -evp_des_encrypt_key_ivec(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ignore_ivec) -{ - struct evp_schedule *ctx = key->schedule->data; - EVP_CIPHER_CTX *c; - DES_cblock ivec; - memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); - c = encryptp ? &ctx->ectx : &ctx->dctx; - EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1); - EVP_Cipher(c, data, data, len); - return 0; -} - -static krb5_error_code -DES_CFB64_encrypt_null_ivec(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ignore_ivec) -{ - DES_cblock ivec; - int num = 0; - DES_key_schedule *s = key->schedule->data; - memset(&ivec, 0, sizeof(ivec)); - - DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp); - return 0; -} - -static krb5_error_code -DES_PCBC_encrypt_key_ivec(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ignore_ivec) -{ - DES_cblock ivec; - DES_key_schedule *s = key->schedule->data; - memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); - - DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp); - return 0; -} -#endif - -/* - * section 6 of draft-brezak-win2k-krb-rc4-hmac-03 - * - * warning: not for small children - */ - -static krb5_error_code -ARCFOUR_subencrypt(krb5_context context, - struct key_data *key, - void *data, - size_t len, - unsigned usage, - void *ivec) -{ - EVP_CIPHER_CTX ctx; - struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); - Checksum k1_c, k2_c, k3_c, cksum; - struct key_data ke; - krb5_keyblock kb; - unsigned char t[4]; - unsigned char *cdata = data; - unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; - krb5_error_code ret; - - t[0] = (usage >> 0) & 0xFF; - t[1] = (usage >> 8) & 0xFF; - t[2] = (usage >> 16) & 0xFF; - t[3] = (usage >> 24) & 0xFF; - - k1_c.checksum.length = sizeof(k1_c_data); - k1_c.checksum.data = k1_c_data; - - ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); - if (ret) - krb5_abortx(context, "hmac failed"); - - memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); - - k2_c.checksum.length = sizeof(k2_c_data); - k2_c.checksum.data = k2_c_data; - - ke.key = &kb; - kb.keyvalue = k2_c.checksum; - - cksum.checksum.length = 16; - cksum.checksum.data = data; - - ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); - if (ret) - krb5_abortx(context, "hmac failed"); - - ke.key = &kb; - kb.keyvalue = k1_c.checksum; - - k3_c.checksum.length = sizeof(k3_c_data); - k3_c.checksum.data = k3_c_data; - - ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c); - if (ret) - krb5_abortx(context, "hmac failed"); - - EVP_CIPHER_CTX_init(&ctx); - - EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1); - EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16); - EVP_CIPHER_CTX_cleanup(&ctx); - - memset (k1_c_data, 0, sizeof(k1_c_data)); - memset (k2_c_data, 0, sizeof(k2_c_data)); - memset (k3_c_data, 0, sizeof(k3_c_data)); - return 0; -} - -static krb5_error_code -ARCFOUR_subdecrypt(krb5_context context, - struct key_data *key, - void *data, - size_t len, - unsigned usage, - void *ivec) -{ - EVP_CIPHER_CTX ctx; - struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); - Checksum k1_c, k2_c, k3_c, cksum; - struct key_data ke; - krb5_keyblock kb; - unsigned char t[4]; - unsigned char *cdata = data; - unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; - unsigned char cksum_data[16]; - krb5_error_code ret; - - t[0] = (usage >> 0) & 0xFF; - t[1] = (usage >> 8) & 0xFF; - t[2] = (usage >> 16) & 0xFF; - t[3] = (usage >> 24) & 0xFF; - - k1_c.checksum.length = sizeof(k1_c_data); - k1_c.checksum.data = k1_c_data; - - ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); - if (ret) - krb5_abortx(context, "hmac failed"); - - memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); - - k2_c.checksum.length = sizeof(k2_c_data); - k2_c.checksum.data = k2_c_data; - - ke.key = &kb; - kb.keyvalue = k1_c.checksum; - - k3_c.checksum.length = sizeof(k3_c_data); - k3_c.checksum.data = k3_c_data; - - ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c); - if (ret) - krb5_abortx(context, "hmac failed"); - - EVP_CIPHER_CTX_init(&ctx); - EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0); - EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16); - EVP_CIPHER_CTX_cleanup(&ctx); - - ke.key = &kb; - kb.keyvalue = k2_c.checksum; - - cksum.checksum.length = 16; - cksum.checksum.data = cksum_data; - - ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); - if (ret) - krb5_abortx(context, "hmac failed"); - - memset (k1_c_data, 0, sizeof(k1_c_data)); - memset (k2_c_data, 0, sizeof(k2_c_data)); - memset (k3_c_data, 0, sizeof(k3_c_data)); - - if (ct_memcmp (cksum.checksum.data, data, 16) != 0) { - krb5_clear_error_message (context); - return KRB5KRB_AP_ERR_BAD_INTEGRITY; - } else { - return 0; - } -} - -/* - * convert the usage numbers used in - * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in - * draft-brezak-win2k-krb-rc4-hmac-04.txt - */ - -static krb5_error_code -usage2arcfour (krb5_context context, unsigned *usage) -{ - switch (*usage) { - case KRB5_KU_AS_REP_ENC_PART : /* 3 */ - *usage = 8; - return 0; - case KRB5_KU_USAGE_SEAL : /* 22 */ - *usage = 13; - return 0; - case KRB5_KU_USAGE_SIGN : /* 23 */ - *usage = 15; - return 0; - case KRB5_KU_USAGE_SEQ: /* 24 */ - *usage = 0; - return 0; - default : - return 0; - } -} - -static krb5_error_code -ARCFOUR_encrypt(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ivec) -{ - krb5_error_code ret; - unsigned keyusage = usage; - - if((ret = usage2arcfour (context, &keyusage)) != 0) - return ret; - - if (encryptp) - return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec); - else - return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec); -} - - -/* - * - */ - -static krb5_error_code -AES_PRF(krb5_context context, - krb5_crypto crypto, - const krb5_data *in, - krb5_data *out) -{ - struct checksum_type *ct = crypto->et->checksum; - krb5_error_code ret; - Checksum result; - krb5_keyblock *derived; - - result.cksumtype = ct->type; - ret = krb5_data_alloc(&result.checksum, ct->checksumsize); - if (ret) { - krb5_set_error_message(context, ret, N_("malloc: out memory", "")); - return ret; + ct = crypto->et->checksum; } - ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result); - if (ret) { - krb5_data_free(&result.checksum); - return ret; + if (ct == NULL) { + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + N_("checksum type not found", "")); + return KRB5_PROG_SUMTYPE_NOSUPP; } - if (result.checksum.length < crypto->et->blocksize) - krb5_abortx(context, "internal prf error"); + *type = ct->type; - derived = NULL; - ret = krb5_derive_key(context, crypto->key.key, - crypto->et->type, "prf", 3, &derived); - if (ret) - krb5_abortx(context, "krb5_derive_key"); + return 0; +} - ret = krb5_data_alloc(out, crypto->et->blocksize); - if (ret) - krb5_abortx(context, "malloc failed"); - { - const EVP_CIPHER *c = (*crypto->et->keytype->evp)(); - EVP_CIPHER_CTX ctx; - - EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */ - EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1); - EVP_Cipher(&ctx, out->data, result.checksum.data, - crypto->et->blocksize); - EVP_CIPHER_CTX_cleanup(&ctx); +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_checksumsize(krb5_context context, + krb5_cksumtype type, + size_t *size) +{ + struct checksum_type *ct = _krb5_find_checksum(type); + if(ct == NULL) { + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + N_("checksum type %d not supported", ""), + type); + return KRB5_PROG_SUMTYPE_NOSUPP; } + *size = ct->checksumsize; + return 0; +} - krb5_data_free(&result.checksum); - krb5_free_keyblock(context, derived); - - return ret; +KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL +krb5_checksum_is_keyed(krb5_context context, + krb5_cksumtype type) +{ + struct checksum_type *ct = _krb5_find_checksum(type); + if(ct == NULL) { + if (context) + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + N_("checksum type %d not supported", ""), + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + return ct->flags & F_KEYED; } -/* - * these should currently be in reverse preference order. - * (only relevant for !F_PSEUDO) */ - -static struct encryption_type enctype_null = { - ETYPE_NULL, - "null", - 1, - 1, - 0, - &keytype_null, - &checksum_none, - NULL, - F_DISABLED, - NULL_encrypt, - 0, - NULL -}; -static struct encryption_type enctype_arcfour_hmac_md5 = { - ETYPE_ARCFOUR_HMAC_MD5, - "arcfour-hmac-md5", - 1, - 1, - 8, - &keytype_arcfour, - &checksum_hmac_md5, - NULL, - F_SPECIAL, - ARCFOUR_encrypt, - 0, - NULL -}; -#ifdef DES3_OLD_ENCTYPE -static struct encryption_type enctype_des3_cbc_md5 = { - ETYPE_DES3_CBC_MD5, - "des3-cbc-md5", - 8, - 8, - 8, - &keytype_des3, - &checksum_rsa_md5, - &checksum_rsa_md5_des3, - 0, - evp_encrypt, - 0, - NULL -}; -#endif -static struct encryption_type enctype_des3_cbc_sha1 = { - ETYPE_DES3_CBC_SHA1, - "des3-cbc-sha1", - 8, - 8, - 8, - &keytype_des3_derived, - &checksum_sha1, - &checksum_hmac_sha1_des3, - F_DERIVED, - evp_encrypt, - 0, - NULL -}; -#ifdef DES3_OLD_ENCTYPE -static struct encryption_type enctype_old_des3_cbc_sha1 = { - ETYPE_OLD_DES3_CBC_SHA1, - "old-des3-cbc-sha1", - 8, - 8, - 8, - &keytype_des3, - &checksum_sha1, - &checksum_hmac_sha1_des3, - 0, - evp_encrypt, - 0, - NULL -}; -#endif -static struct encryption_type enctype_aes128_cts_hmac_sha1 = { - ETYPE_AES128_CTS_HMAC_SHA1_96, - "aes128-cts-hmac-sha1-96", - 16, - 1, - 16, - &keytype_aes128, - &checksum_sha1, - &checksum_hmac_sha1_aes128, - F_DERIVED, - evp_encrypt_cts, - 16, - AES_PRF -}; -static struct encryption_type enctype_aes256_cts_hmac_sha1 = { - ETYPE_AES256_CTS_HMAC_SHA1_96, - "aes256-cts-hmac-sha1-96", - 16, - 1, - 16, - &keytype_aes256, - &checksum_sha1, - &checksum_hmac_sha1_aes256, - F_DERIVED, - evp_encrypt_cts, - 16, - AES_PRF -}; -static struct encryption_type enctype_des3_cbc_none = { - ETYPE_DES3_CBC_NONE, - "des3-cbc-none", - 8, - 8, - 0, - &keytype_des3_derived, - &checksum_none, - NULL, - F_PSEUDO, - evp_encrypt, - 0, - NULL -}; -#ifdef HEIM_WEAK_CRYPTO -static struct encryption_type enctype_des_cbc_crc = { - ETYPE_DES_CBC_CRC, - "des-cbc-crc", - 8, - 8, - 8, - &keytype_des, - &checksum_crc32, - NULL, - F_DISABLED|F_WEAK, - evp_des_encrypt_key_ivec, - 0, - NULL -}; -static struct encryption_type enctype_des_cbc_md4 = { - ETYPE_DES_CBC_MD4, - "des-cbc-md4", - 8, - 8, - 8, - &keytype_des, - &checksum_rsa_md4, - &checksum_rsa_md4_des, - F_DISABLED|F_WEAK, - evp_des_encrypt_null_ivec, - 0, - NULL -}; -static struct encryption_type enctype_des_cbc_md5 = { - ETYPE_DES_CBC_MD5, - "des-cbc-md5", - 8, - 8, - 8, - &keytype_des, - &checksum_rsa_md5, - &checksum_rsa_md5_des, - F_DISABLED|F_WEAK, - evp_des_encrypt_null_ivec, - 0, - NULL -}; -static struct encryption_type enctype_des_cbc_none = { - ETYPE_DES_CBC_NONE, - "des-cbc-none", - 8, - 8, - 0, - &keytype_des, - &checksum_none, - NULL, - F_PSEUDO|F_DISABLED|F_WEAK, - evp_des_encrypt_null_ivec, - 0, - NULL -}; -static struct encryption_type enctype_des_cfb64_none = { - ETYPE_DES_CFB64_NONE, - "des-cfb64-none", - 1, - 1, - 0, - &keytype_des_old, - &checksum_none, - NULL, - F_PSEUDO|F_DISABLED|F_WEAK, - DES_CFB64_encrypt_null_ivec, - 0, - NULL -}; -static struct encryption_type enctype_des_pcbc_none = { - ETYPE_DES_PCBC_NONE, - "des-pcbc-none", - 8, - 8, - 0, - &keytype_des_old, - &checksum_none, - NULL, - F_PSEUDO|F_DISABLED|F_WEAK, - DES_PCBC_encrypt_key_ivec, - 0, - NULL -}; -#endif /* HEIM_WEAK_CRYPTO */ - -static struct encryption_type *etypes[] = { - &enctype_aes256_cts_hmac_sha1, - &enctype_aes128_cts_hmac_sha1, - &enctype_des3_cbc_sha1, - &enctype_des3_cbc_none, /* used by the gss-api mech */ - &enctype_arcfour_hmac_md5, -#ifdef DES3_OLD_ENCTYPE - &enctype_des3_cbc_md5, - &enctype_old_des3_cbc_sha1, -#endif -#ifdef HEIM_WEAK_CRYPTO - &enctype_des_cbc_crc, - &enctype_des_cbc_md4, - &enctype_des_cbc_md5, - &enctype_des_cbc_none, - &enctype_des_cfb64_none, - &enctype_des_pcbc_none, -#endif - &enctype_null -}; +KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL +krb5_checksum_is_collision_proof(krb5_context context, + krb5_cksumtype type) +{ + struct checksum_type *ct = _krb5_find_checksum(type); + if(ct == NULL) { + if (context) + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + N_("checksum type %d not supported", ""), + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + return ct->flags & F_CPROOF; +} -static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]); +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_checksum_disable(krb5_context context, + krb5_cksumtype type) +{ + struct checksum_type *ct = _krb5_find_checksum(type); + if(ct == NULL) { + if (context) + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + N_("checksum type %d not supported", ""), + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + ct->flags |= F_DISABLED; + return 0; +} +/************************************************************ + * * + ************************************************************/ -static struct encryption_type * -_find_enctype(krb5_enctype type) +struct encryption_type * +_krb5_find_enctype(krb5_enctype type) { int i; - for(i = 0; i < num_etypes; i++) - if(etypes[i]->type == type) - return etypes[i]; + for(i = 0; i < _krb5_num_etypes; i++) + if(_krb5_etypes[i]->type == type) + return _krb5_etypes[i]; return NULL; } @@ -2786,7 +640,7 @@ krb5_enctype_to_string(krb5_context context, char **string) { struct encryption_type *e; - e = _find_enctype(etype); + e = _krb5_find_enctype(etype); if(e == NULL) { krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, N_("encryption type %d not supported", ""), @@ -2808,9 +662,9 @@ krb5_string_to_enctype(krb5_context context, krb5_enctype *etype) { int i; - for(i = 0; i < num_etypes; i++) - if(strcasecmp(etypes[i]->name, string) == 0){ - *etype = etypes[i]->type; + for(i = 0; i < _krb5_num_etypes; i++) + if(strcasecmp(_krb5_etypes[i]->name, string) == 0){ + *etype = _krb5_etypes[i]->type; return 0; } krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, @@ -2824,7 +678,7 @@ krb5_enctype_to_keytype(krb5_context context, krb5_enctype etype, krb5_keytype *keytype) { - struct encryption_type *e = _find_enctype(etype); + struct encryption_type *e = _krb5_find_enctype(etype); if(e == NULL) { krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, N_("encryption type %d not supported", ""), @@ -2839,7 +693,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_enctype_valid(krb5_context context, krb5_enctype etype) { - struct encryption_type *e = _find_enctype(etype); + struct encryption_type *e = _krb5_find_enctype(etype); if(e == NULL) { krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, N_("encryption type %d not supported", ""), @@ -2877,11 +731,11 @@ krb5_cksumtype_to_enctype(krb5_context context, *etype = ETYPE_NULL; - for(i = 0; i < num_etypes; i++) { - if(etypes[i]->keyed_checksum && - etypes[i]->keyed_checksum->type == ctype) + for(i = 0; i < _krb5_num_etypes; i++) { + if(_krb5_etypes[i]->keyed_checksum && + _krb5_etypes[i]->keyed_checksum->type == ctype) { - *etype = etypes[i]->type; + *etype = _krb5_etypes[i]->type; return 0; } } @@ -2897,7 +751,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_cksumtype_valid(krb5_context context, krb5_cksumtype ctype) { - struct checksum_type *c = _find_checksum(ctype); + struct checksum_type *c = _krb5_find_checksum(ctype); if (c == NULL) { krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, N_("checksum type %d not supported", ""), @@ -3977,85 +1831,12 @@ krb5_decrypt_EncryptedData(krb5_context context, * * ************************************************************/ -#define ENTROPY_NEEDED 128 - -static int -seed_something(void) -{ - char buf[1024], seedfile[256]; - - /* If there is a seed file, load it. But such a file cannot be trusted, - so use 0 for the entropy estimate */ - if (RAND_file_name(seedfile, sizeof(seedfile))) { - int fd; - fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC); - if (fd >= 0) { - ssize_t ret; - rk_cloexec(fd); - ret = read(fd, buf, sizeof(buf)); - if (ret > 0) - RAND_add(buf, ret, 0.0); - close(fd); - } else - seedfile[0] = '\0'; - } else - seedfile[0] = '\0'; - - /* Calling RAND_status() will try to use /dev/urandom if it exists so - we do not have to deal with it. */ - if (RAND_status() != 1) { -#ifndef _WIN32 - krb5_context context; - const char *p; - - /* Try using egd */ - if (!krb5_init_context(&context)) { - p = krb5_config_get_string(context, NULL, "libdefaults", - "egd_socket", NULL); - if (p != NULL) - RAND_egd_bytes(p, ENTROPY_NEEDED); - krb5_free_context(context); - } -#else - /* TODO: Once a Windows CryptoAPI RAND method is defined, we - can use that and failover to another method. */ -#endif - } - - if (RAND_status() == 1) { - /* Update the seed file */ - if (seedfile[0]) - RAND_write_file(seedfile); - - return 0; - } else - return -1; -} - -KRB5_LIB_FUNCTION void KRB5_LIB_CALL -krb5_generate_random_block(void *buf, size_t len) -{ - static int rng_initialized = 0; - - HEIMDAL_MUTEX_lock(&crypto_mutex); - if (!rng_initialized) { - if (seed_something()) - krb5_abortx(NULL, "Fatal: could not seed the " - "random number generator"); - - rng_initialized = 1; - } - HEIMDAL_MUTEX_unlock(&crypto_mutex); - if (RAND_bytes(buf, len) <= 0) - krb5_abortx(NULL, "Failed to generate random block"); -} - -static krb5_error_code -derive_key(krb5_context context, - struct encryption_type *et, - struct key_data *key, - const void *constant, - size_t len) +krb5_error_code +_krb5_derive_key(krb5_context context, + struct encryption_type *et, + struct key_data *key, + const void *constant, + size_t len) { unsigned char *k = NULL; unsigned int nblocks = 0, i; @@ -4117,7 +1898,7 @@ derive_key(krb5_context context, /* XXX keytype dependent post-processing */ switch(kt->type) { case KEYTYPE_DES3: - DES3_random_to_key(context, key->key, k, nblocks * et->blocksize); + _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize); break; case KEYTYPE_AES128: case KEYTYPE_AES256: @@ -4170,7 +1951,7 @@ krb5_derive_key(krb5_context context, *derived_key = NULL; - et = _find_enctype (etype); + et = _krb5_find_enctype (etype); if (et == NULL) { krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, N_("encryption type %d not supported", ""), @@ -4183,10 +1964,10 @@ krb5_derive_key(krb5_context context, return ret; d.schedule = NULL; - ret = derive_key(context, et, &d, constant, constant_len); + ret = _krb5_derive_key(context, et, &d, constant, constant_len); if (ret == 0) ret = krb5_copy_keyblock(context, d.key, derived_key); - free_key_data(context, &d, et); + _krb5_free_key_data(context, &d, et); return ret; } @@ -4212,7 +1993,7 @@ _get_derived_key(krb5_context context, } krb5_copy_keyblock(context, crypto->key.key, &d->key); _krb5_put_int(constant, usage, 5); - derive_key(context, crypto->et, d, constant, sizeof(constant)); + _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant)); *key = d; return 0; } @@ -4249,7 +2030,7 @@ krb5_crypto_init(krb5_context context, } if(etype == ETYPE_NULL) etype = key->keytype; - (*crypto)->et = _find_enctype(etype); + (*crypto)->et = _krb5_find_enctype(etype); if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) { free(*crypto); *crypto = NULL; @@ -4288,8 +2069,8 @@ free_key_schedule(krb5_context context, krb5_free_data(context, key->schedule); } -static void -free_key_data(krb5_context context, struct key_data *key, +void +_krb5_free_key_data(krb5_context context, struct key_data *key, struct encryption_type *et) { krb5_free_keyblock(context, key->key); @@ -4303,7 +2084,7 @@ static void free_key_usage(krb5_context context, struct key_usage *ku, struct encryption_type *et) { - free_key_data(context, &ku->key, et); + _krb5_free_key_data(context, &ku->key, et); } /** @@ -4326,7 +2107,7 @@ krb5_crypto_destroy(krb5_context context, for(i = 0; i < crypto->num_key_usage; i++) free_key_usage(context, &crypto->key_usage[i], crypto->et); free(crypto->key_usage); - free_key_data(context, &crypto->key, crypto->et); + _krb5_free_key_data(context, &crypto->key, crypto->et); free (crypto); return 0; } @@ -4431,7 +2212,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_enctype_disable(krb5_context context, krb5_enctype enctype) { - struct encryption_type *et = _find_enctype(enctype); + struct encryption_type *et = _krb5_find_enctype(enctype); if(et == NULL) { if (context) krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, @@ -4458,7 +2239,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_enctype_enable(krb5_context context, krb5_enctype enctype) { - struct encryption_type *et = _find_enctype(enctype); + struct encryption_type *et = _krb5_find_enctype(enctype); if(et == NULL) { if (context) krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, @@ -4487,80 +2268,16 @@ krb5_allow_weak_crypto(krb5_context context, { int i; - for(i = 0; i < num_etypes; i++) - if(etypes[i]->flags & F_WEAK) { + for(i = 0; i < _krb5_num_etypes; i++) + if(_krb5_etypes[i]->flags & F_WEAK) { if(enable) - etypes[i]->flags &= ~F_DISABLED; + _krb5_etypes[i]->flags &= ~F_DISABLED; else - etypes[i]->flags |= F_DISABLED; + _krb5_etypes[i]->flags |= F_DISABLED; } return 0; } - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_string_to_key_derived(krb5_context context, - const void *str, - size_t len, - krb5_enctype etype, - krb5_keyblock *key) -{ - struct encryption_type *et = _find_enctype(etype); - krb5_error_code ret; - struct key_data kd; - size_t keylen; - u_char *tmp; - - if(et == NULL) { - krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, - N_("encryption type %d not supported", ""), - etype); - return KRB5_PROG_ETYPE_NOSUPP; - } - keylen = et->keytype->bits / 8; - - ALLOC(kd.key, 1); - if(kd.key == NULL) { - krb5_set_error_message (context, ENOMEM, - N_("malloc: out of memory", "")); - return ENOMEM; - } - ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); - if(ret) { - free(kd.key); - return ret; - } - kd.key->keytype = etype; - tmp = malloc (keylen); - if(tmp == NULL) { - krb5_free_keyblock(context, kd.key); - krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - ret = _krb5_n_fold(str, len, tmp, keylen); - if (ret) { - free(tmp); - krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); - return ret; - } - kd.schedule = NULL; - DES3_random_to_key(context, kd.key, tmp, keylen); - memset(tmp, 0, keylen); - free(tmp); - ret = derive_key(context, - et, - &kd, - "kerberos", /* XXX well known constant */ - strlen("kerberos")); - if (ret) { - free_key_data(context, &kd, et); - return ret; - } - ret = krb5_copy_keyblock_contents(context, kd.key, key); - free_key_data(context, &kd, et); - return ret; -} - static size_t wrapped_length (krb5_context context, krb5_crypto crypto, @@ -4678,7 +2395,7 @@ krb5_random_to_key(krb5_context context, krb5_keyblock *key) { krb5_error_code ret; - struct encryption_type *et = _find_enctype(type); + struct encryption_type *et = _krb5_find_enctype(type); if(et == NULL) { krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, N_("encryption type %d not supported", ""), @@ -4705,261 +2422,6 @@ krb5_random_to_key(krb5_context context, return 0; } -krb5_error_code -_krb5_pk_octetstring2key(krb5_context context, - krb5_enctype type, - const void *dhdata, - size_t dhsize, - const heim_octet_string *c_n, - const heim_octet_string *k_n, - krb5_keyblock *key) -{ - struct encryption_type *et = _find_enctype(type); - krb5_error_code ret; - size_t keylen, offset; - void *keydata; - unsigned char counter; - unsigned char shaoutput[SHA_DIGEST_LENGTH]; - EVP_MD_CTX *m; - - if(et == NULL) { - krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, - N_("encryption type %d not supported", ""), - type); - return KRB5_PROG_ETYPE_NOSUPP; - } - keylen = (et->keytype->bits + 7) / 8; - - keydata = malloc(keylen); - if (keydata == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - - m = EVP_MD_CTX_create(); - if (m == NULL) { - free(keydata); - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - - counter = 0; - offset = 0; - do { - - EVP_DigestInit_ex(m, EVP_sha1(), NULL); - EVP_DigestUpdate(m, &counter, 1); - EVP_DigestUpdate(m, dhdata, dhsize); - - if (c_n) - EVP_DigestUpdate(m, c_n->data, c_n->length); - if (k_n) - EVP_DigestUpdate(m, k_n->data, k_n->length); - - EVP_DigestFinal_ex(m, shaoutput, NULL); - - memcpy((unsigned char *)keydata + offset, - shaoutput, - min(keylen - offset, sizeof(shaoutput))); - - offset += sizeof(shaoutput); - counter++; - } while(offset < keylen); - memset(shaoutput, 0, sizeof(shaoutput)); - - EVP_MD_CTX_destroy(m); - - ret = krb5_random_to_key(context, type, keydata, keylen, key); - memset(keydata, 0, sizeof(keylen)); - free(keydata); - return ret; -} - -static krb5_error_code -encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data) -{ - KRB5PrincipalName pn; - krb5_error_code ret; - size_t size; - - pn.principalName = p->name; - pn.realm = p->realm; - - ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length, - &pn, &size, ret); - if (ret) { - krb5_data_zero(data); - krb5_set_error_message(context, ret, - N_("Failed to encode KRB5PrincipalName", "")); - return ret; - } - if (data->length != size) - krb5_abortx(context, "asn1 compiler internal error"); - return 0; -} - -static krb5_error_code -encode_otherinfo(krb5_context context, - const AlgorithmIdentifier *ai, - krb5_const_principal client, - krb5_const_principal server, - krb5_enctype enctype, - const krb5_data *as_req, - const krb5_data *pk_as_rep, - const Ticket *ticket, - krb5_data *other) -{ - PkinitSP80056AOtherInfo otherinfo; - PkinitSuppPubInfo pubinfo; - krb5_error_code ret; - krb5_data pub; - size_t size; - - krb5_data_zero(other); - memset(&otherinfo, 0, sizeof(otherinfo)); - memset(&pubinfo, 0, sizeof(pubinfo)); - - pubinfo.enctype = enctype; - pubinfo.as_REQ = *as_req; - pubinfo.pk_as_rep = *pk_as_rep; - pubinfo.ticket = *ticket; - ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length, - &pubinfo, &size, ret); - if (ret) { - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); - return ret; - } - if (pub.length != size) - krb5_abortx(context, "asn1 compiler internal error"); - - ret = encode_uvinfo(context, client, &otherinfo.partyUInfo); - if (ret) { - free(pub.data); - return ret; - } - ret = encode_uvinfo(context, server, &otherinfo.partyVInfo); - if (ret) { - free(otherinfo.partyUInfo.data); - free(pub.data); - return ret; - } - - otherinfo.algorithmID = *ai; - otherinfo.suppPubInfo = &pub; - - ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length, - &otherinfo, &size, ret); - free(otherinfo.partyUInfo.data); - free(otherinfo.partyVInfo.data); - free(pub.data); - if (ret) { - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); - return ret; - } - if (other->length != size) - krb5_abortx(context, "asn1 compiler internal error"); - - return 0; -} - -krb5_error_code -_krb5_pk_kdf(krb5_context context, - const struct AlgorithmIdentifier *ai, - const void *dhdata, - size_t dhsize, - krb5_const_principal client, - krb5_const_principal server, - krb5_enctype enctype, - const krb5_data *as_req, - const krb5_data *pk_as_rep, - const Ticket *ticket, - krb5_keyblock *key) -{ - struct encryption_type *et; - krb5_error_code ret; - krb5_data other; - size_t keylen, offset; - uint32_t counter; - unsigned char *keydata; - unsigned char shaoutput[SHA_DIGEST_LENGTH]; - EVP_MD_CTX *m; - - if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) != 0) { - krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, - N_("KDF not supported", "")); - return KRB5_PROG_ETYPE_NOSUPP; - } - if (ai->parameters != NULL && - (ai->parameters->length != 2 || - memcmp(ai->parameters->data, "\x05\x00", 2) != 0)) - { - krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, - N_("kdf params not NULL or the NULL-type", - "")); - return KRB5_PROG_ETYPE_NOSUPP; - } - - et = _find_enctype(enctype); - if(et == NULL) { - krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, - N_("encryption type %d not supported", ""), - enctype); - return KRB5_PROG_ETYPE_NOSUPP; - } - keylen = (et->keytype->bits + 7) / 8; - - keydata = malloc(keylen); - if (keydata == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - - ret = encode_otherinfo(context, ai, client, server, - enctype, as_req, pk_as_rep, ticket, &other); - if (ret) { - free(keydata); - return ret; - } - - m = EVP_MD_CTX_create(); - if (m == NULL) { - free(keydata); - free(other.data); - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } - - offset = 0; - counter = 1; - do { - unsigned char cdata[4]; - - EVP_DigestInit_ex(m, EVP_sha1(), NULL); - _krb5_put_int(cdata, counter, 4); - EVP_DigestUpdate(m, cdata, 4); - EVP_DigestUpdate(m, dhdata, dhsize); - EVP_DigestUpdate(m, other.data, other.length); - - EVP_DigestFinal_ex(m, shaoutput, NULL); - - memcpy((unsigned char *)keydata + offset, - shaoutput, - min(keylen - offset, sizeof(shaoutput))); - - offset += sizeof(shaoutput); - counter++; - } while(offset < keylen); - memset(shaoutput, 0, sizeof(shaoutput)); - - EVP_MD_CTX_destroy(m); - free(other.data); - - ret = krb5_random_to_key(context, enctype, keydata, keylen, key); - memset(keydata, 0, sizeof(keylen)); - free(keydata); - - return ret; -} KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL @@ -4967,7 +2429,7 @@ krb5_crypto_prf_length(krb5_context context, krb5_enctype type, size_t *length) { - struct encryption_type *et = _find_enctype(type); + struct encryption_type *et = _krb5_find_enctype(type); if(et == NULL || et->prf_length == 0) { krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, @@ -5136,10 +2598,10 @@ krb5_keytype_to_enctypes (krb5_context context, unsigned n = 0; krb5_enctype *ret; - for (i = num_etypes - 1; i >= 0; --i) { - if (etypes[i]->keytype->type == keytype - && !(etypes[i]->flags & F_PSEUDO) - && krb5_enctype_valid(context, etypes[i]->type) == 0) + for (i = _krb5_num_etypes - 1; i >= 0; --i) { + if (_krb5_etypes[i]->keytype->type == keytype + && !(_krb5_etypes[i]->flags & F_PSEUDO) + && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0) ++n; } if (n == 0) { @@ -5154,11 +2616,11 @@ krb5_keytype_to_enctypes (krb5_context context, return ENOMEM; } n = 0; - for (i = num_etypes - 1; i >= 0; --i) { - if (etypes[i]->keytype->type == keytype - && !(etypes[i]->flags & F_PSEUDO) - && krb5_enctype_valid(context, etypes[i]->type) == 0) - ret[n++] = etypes[i]->type; + for (i = _krb5_num_etypes - 1; i >= 0; --i) { + if (_krb5_etypes[i]->keytype->type == keytype + && !(_krb5_etypes[i]->flags & F_PSEUDO) + && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0) + ret[n++] = _krb5_etypes[i]->type; } *len = n; *val = ret; @@ -5178,8 +2640,8 @@ krb5_enctypes_compatible_keys(krb5_context context, krb5_enctype etype1, krb5_enctype etype2) { - struct encryption_type *e1 = _find_enctype(etype1); - struct encryption_type *e2 = _find_enctype(etype2); + struct encryption_type *e1 = _krb5_find_enctype(etype1); + struct encryption_type *e2 = _krb5_find_enctype(etype2); return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype; } diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c index c4c202be5d..f62a5532ab 100644 --- a/source4/heimdal/lib/krb5/data.c +++ b/source4/heimdal/lib/krb5/data.c @@ -207,3 +207,22 @@ krb5_data_cmp(const krb5_data *data1, const krb5_data *data2) return data1->length - data2->length; return memcmp(data1->data, data2->data, data1->length); } + +/** + * Compare to data not exposing timing information from the checksum data + * + * @param data1 krb5_data to compare + * @param data2 krb5_data to compare + * + * @return returns zero for same data, otherwise non zero. + * + * @ingroup krb5 + */ + +KRB5_LIB_FUNCTION int KRB5_LIB_CALL +krb5_data_ct_cmp(const krb5_data *data1, const krb5_data *data2) +{ + if (data1->length != data2->length) + return data1->length - data2->length; + return ct_memcmp(data1->data, data2->data, data1->length); +} diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 8f9d462190..9e06770e64 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -36,6 +36,11 @@ #include "krb5_locl.h" #include +static krb5_error_code +get_cred_kdc_capath(krb5_context, krb5_kdc_flags, + krb5_ccache, krb5_creds *, krb5_principal, + Ticket *, krb5_creds **, krb5_creds ***); + /* * Take the `body' and encode it into `padata' using the credentials * in `creds'. @@ -710,34 +715,20 @@ add_cred(krb5_context context, krb5_creds const *tkt, krb5_creds ***tgts) return ret; } -/* -get_cred(server) - creds = cc_get_cred(server) - if(creds) return creds - tgt = cc_get_cred(krbtgt/server_realm@any_realm) - if(tgt) - return get_cred_tgt(server, tgt) - if(client_realm == server_realm) - return NULL - tgt = get_cred(krbtgt/server_realm@client_realm) - while(tgt_inst != server_realm) - tgt = get_cred(krbtgt/server_realm@tgt_inst) - return get_cred_tgt(server, tgt) - */ - static krb5_error_code -get_cred_kdc_capath(krb5_context context, - krb5_kdc_flags flags, - krb5_ccache ccache, - krb5_creds *in_creds, - krb5_principal impersonate_principal, - Ticket *second_ticket, - krb5_creds **out_creds, - krb5_creds ***ret_tgts) +get_cred_kdc_capath_worker(krb5_context context, + krb5_kdc_flags flags, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_const_realm try_realm, + krb5_principal impersonate_principal, + Ticket *second_ticket, + krb5_creds **out_creds, + krb5_creds ***ret_tgts) { krb5_error_code ret; krb5_creds *tgt, tmp_creds; - krb5_const_realm client_realm, server_realm, try_realm; + krb5_const_realm client_realm, server_realm; int ok_as_delegate = 1; *out_creds = NULL; @@ -749,11 +740,6 @@ get_cred_kdc_capath(krb5_context context, if(ret) return ret; - try_realm = krb5_config_get_string(context, NULL, "capaths", - client_realm, server_realm, NULL); - if (try_realm == NULL) - try_realm = client_realm; - ret = krb5_make_principal(context, &tmp_creds.server, try_realm, @@ -770,7 +756,7 @@ get_cred_kdc_capath(krb5_context context, ret = find_cred(context, ccache, tmp_creds.server, *ret_tgts, &tgts); if(ret == 0){ - if (try_realm != client_realm) + if (strcmp(try_realm, client_realm) != 0) ok_as_delegate = tgts.flags.b.ok_as_delegate; *out_creds = calloc(1, sizeof(**out_creds)); @@ -863,6 +849,56 @@ get_cred_kdc_capath(krb5_context context, return ret; } +/* +get_cred(server) + creds = cc_get_cred(server) + if(creds) return creds + tgt = cc_get_cred(krbtgt/server_realm@any_realm) + if(tgt) + return get_cred_tgt(server, tgt) + if(client_realm == server_realm) + return NULL + tgt = get_cred(krbtgt/server_realm@client_realm) + while(tgt_inst != server_realm) + tgt = get_cred(krbtgt/server_realm@tgt_inst) + return get_cred_tgt(server, tgt) + */ + +static krb5_error_code +get_cred_kdc_capath(krb5_context context, + krb5_kdc_flags flags, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_principal impersonate_principal, + Ticket *second_ticket, + krb5_creds **out_creds, + krb5_creds ***ret_tgts) +{ + krb5_error_code ret; + krb5_const_realm client_realm, server_realm, try_realm; + + client_realm = krb5_principal_get_realm(context, in_creds->client); + server_realm = krb5_principal_get_realm(context, in_creds->server); + + try_realm = client_realm; + ret = get_cred_kdc_capath_worker(context, flags, ccache, in_creds, try_realm, + impersonate_principal, second_ticket, out_creds, + ret_tgts); + + if (ret == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) { + try_realm = krb5_config_get_string(context, NULL, "capaths", + client_realm, server_realm, NULL); + + if (try_realm != NULL && strcmp(try_realm, client_realm)) { + ret = get_cred_kdc_capath_worker(context, flags, ccache, in_creds, + try_realm, impersonate_principal, + second_ticket, out_creds, ret_tgts); + } + } + + return ret; +} + static krb5_error_code get_cred_kdc_referral(krb5_context context, krb5_kdc_flags flags, diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 2fdb76d757..d8d038e7bb 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -120,6 +120,8 @@ struct sockaddr_dl; #include +#include + #define HEIMDAL_TEXTDOMAIN "heimdal_krb5" #ifdef LIBINTL @@ -176,6 +178,9 @@ struct _krb5_krb_auth_data; #ifdef PKINIT #include #endif + +#include "crypto.h" + #include #include "heim_threads.h" diff --git a/source4/heimdal/lib/krb5/misc.c b/source4/heimdal/lib/krb5/misc.c index b76c1b584d..733d20f174 100644 --- a/source4/heimdal/lib/krb5/misc.c +++ b/source4/heimdal/lib/krb5/misc.c @@ -82,3 +82,10 @@ out: krb5_clear_error_message(context); return ret; } + +krb5_error_code +_krb5_enomem(krb5_context context) +{ + krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); + return ENOMEM; +} diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c index 7ed91b0768..93489b607b 100644 --- a/source4/heimdal/lib/krb5/mit_glue.c +++ b/source4/heimdal/lib/krb5/mit_glue.c @@ -79,8 +79,7 @@ krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key, return ret; if (data_cksum.cksumtype == cksum->cksumtype - && data_cksum.checksum.length == cksum->checksum.length - && ct_memcmp(data_cksum.checksum.data, cksum->checksum.data, cksum->checksum.length) == 0) + && krb5_data_ct_cmp(&data_cksum.checksum, &cksum->checksum) == 0) *valid = 1; krb5_free_checksum_contents(context, &data_cksum); diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 69d9879330..d50052c8bc 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -75,6 +75,43 @@ struct krb5_pac_data { static const char zeros[PAC_ALIGNMENT] = { 0 }; +/* + * HMAC-MD5 checksum over any key (needed for the PAC routines) + */ + +static krb5_error_code +HMAC_MD5_any_checksum(krb5_context context, + const krb5_keyblock *key, + const void *data, + size_t len, + unsigned usage, + Checksum *result) +{ + struct key_data local_key; + krb5_error_code ret; + + memset(&local_key, 0, sizeof(local_key)); + + ret = krb5_copy_keyblock(context, key, &local_key.key); + if (ret) + return ret; + + ret = krb5_data_alloc (&result->checksum, 16); + if (ret) { + krb5_free_keyblock(context, local_key.key); + return ret; + } + + result->cksumtype = CKSUMTYPE_HMAC_MD5; + ret = _krb5_HMAC_MD5_checksum(context, &local_key, data, len, usage, result); + if (ret) + krb5_data_free(&result->checksum); + + krb5_free_keyblock(context, local_key.key); + return ret; +} + + /* * */ @@ -90,15 +127,13 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, p = calloc(1, sizeof(*p)); if (p == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); + ret = _krb5_enomem(context); goto out; } sp = krb5_storage_from_readonly_mem(ptr, len); if (sp == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); + ret = _krb5_enomem(context); goto out; } krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); @@ -121,8 +156,7 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, p->pac = calloc(1, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (tmp - 1))); if (p->pac == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); + ret = _krb5_enomem(context); goto out; } @@ -232,26 +266,22 @@ krb5_pac_init(krb5_context context, krb5_pac *pac) p = calloc(1, sizeof(*p)); if (p == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; + return _krb5_enomem(context); } p->pac = calloc(1, sizeof(*p->pac)); if (p->pac == NULL) { free(p); - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; + return _krb5_enomem(context); } ret = krb5_data_alloc(&p->data, PACTYPE_SIZE); if (ret) { free (p->pac); free(p); - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); - return ret; + return _krb5_enomem(context); } - *pac = p; return 0; } @@ -269,10 +299,9 @@ krb5_pac_add_buffer(krb5_context context, krb5_pac p, ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * len)); - if (ptr == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } + if (ptr == NULL) + return _krb5_enomem(context); + p->pac = ptr; for (i = 0; i < len; i++) @@ -379,8 +408,7 @@ krb5_pac_get_types(krb5_context context, *types = calloc(p->pac->numbuffers, sizeof(*types)); if (*types == NULL) { *len = 0; - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; + return _krb5_enomem(context); } for (i = 0; i < p->pac->numbuffers; i++) (*types)[i] = p->pac->buffers[i].type; @@ -421,10 +449,9 @@ verify_checksum(krb5_context context, sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo, sig->buffersize); - if (sp == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } + if (sp == NULL) + return _krb5_enomem(context); + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); CHECK(ret, krb5_ret_uint32(sp, &type), out); @@ -433,8 +460,7 @@ verify_checksum(krb5_context context, sig->buffersize - krb5_storage_seek(sp, 0, SEEK_CUR); cksum.checksum.data = malloc(cksum.checksum.length); if (cksum.checksum.data == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); + ret = _krb5_enomem(context); goto out; } ret = krb5_storage_read(sp, cksum.checksum.data, cksum.checksum.length); @@ -459,20 +485,23 @@ verify_checksum(krb5_context context, * for the same issue in MIT, and * http://blogs.msdn.com/b/openspecification/archive/2010/01/01/verifying-the-server-signature-in-kerberos-privilege-account-certificate.aspx * for Microsoft's explaination */ + if (cksum.cksumtype == CKSUMTYPE_HMAC_MD5) { Checksum local_checksum; - ret = HMAC_MD5_any_checksum(context, key, ptr, len, KRB5_KU_OTHER_CKSUM, &local_checksum); + memset(&local_checksum, 0, sizeof(local_checksum)); - if(local_checksum.checksum.length != cksum.checksum.length || - ct_memcmp(local_checksum.checksum.data, cksum.checksum.data, local_checksum.checksum.length)) { + ret = HMAC_MD5_any_checksum(context, key, ptr, len, + KRB5_KU_OTHER_CKSUM, &local_checksum); + + if (ret != 0 || krb5_data_ct_cmp(&local_checksum.checksum, &cksum.checksum) != 0) { ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; krb5_set_error_message(context, ret, - N_("PAC integrity check failed for hmac-md5 checksum", "")); - } else { - ret = 0; + N_("PAC integrity check failed for " + "hmac-md5 checksum", "")); } krb5_data_free(&local_checksum.checksum); + } else { krb5_crypto crypto = NULL; @@ -516,8 +545,10 @@ create_checksum(krb5_context context, * for the same issue in MIT, and * http://blogs.msdn.com/b/openspecification/archive/2010/01/01/verifying-the-server-signature-in-kerberos-privilege-account-certificate.aspx * for Microsoft's explaination */ + if (cksumtype == CKSUMTYPE_HMAC_MD5) { - ret = HMAC_MD5_any_checksum(context, key, data, datalen, KRB5_KU_OTHER_CKSUM, &cksum); + ret = HMAC_MD5_any_checksum(context, key, data, datalen, + KRB5_KU_OTHER_CKSUM, &cksum); } else { ret = krb5_crypto_init(context, key, 0, &crypto); if (ret) @@ -572,10 +603,8 @@ verify_logonname(krb5_context context, sp = krb5_storage_from_readonly_mem((const char *)data->data + logon_name->offset_lo, logon_name->buffersize); - if (sp == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } + if (sp == NULL) + return _krb5_enomem(context); krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); @@ -602,8 +631,7 @@ verify_logonname(krb5_context context, s = malloc(len); if (s == NULL) { krb5_storage_free(sp); - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; + return _krb5_enomem(context); } ret = krb5_storage_read(sp, s, len); if (ret != len) { @@ -619,10 +647,9 @@ verify_logonname(krb5_context context, unsigned int flags = WIND_RW_LE; ucs2 = malloc(sizeof(ucs2[0]) * ucs2len); - if (ucs2 == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } + if (ucs2 == NULL) + return _krb5_enomem(context); + ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len); free(s); if (ret) { @@ -640,8 +667,7 @@ verify_logonname(krb5_context context, s = malloc(u8len); if (s == NULL) { free(ucs2); - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; + return _krb5_enomem(context); } ret = wind_ucs2utf8(ucs2, ucs2len, s, &u8len); free(ucs2); @@ -687,10 +713,9 @@ build_logon_name(krb5_context context, krb5_data_zero(logon); sp = krb5_storage_emem(); - if (sp == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } + if (sp == NULL) + return _krb5_enomem(context); + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); CHECK(ret, krb5_store_uint32(sp, t & 0xffffffff), out); @@ -708,7 +733,7 @@ build_logon_name(krb5_context context, #if 1 /* cheat for now */ s2 = malloc(len * 2); if (s2 == NULL) { - ret = ENOMEM; + ret = _krb5_enomem(context); free(s); goto out; } @@ -724,7 +749,7 @@ build_logon_name(krb5_context context, ret = krb5_storage_write(sp, s2, len * 2); free(s2); if (ret != len * 2) { - ret = ENOMEM; + ret = _krb5_enomem(context); goto out; } ret = krb5_storage_to_data(sp, logon); @@ -851,10 +876,9 @@ fill_zeros(krb5_context context, krb5_storage *sp, size_t len) if (l > sizeof(zeros)) l = sizeof(zeros); sret = krb5_storage_write(sp, zeros, l); - if (sret <= 0) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } + if (sret <= 0) + return _krb5_enomem(context); + len -= sret; } return 0; @@ -924,10 +948,9 @@ _krb5_pac_sign(krb5_context context, void *ptr; ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (p->pac->numbuffers + num - 1))); - if (ptr == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } + if (ptr == NULL) + return _krb5_enomem(context); + p->pac = ptr; if (p->logon_name == NULL) { @@ -962,17 +985,15 @@ _krb5_pac_sign(krb5_context context, /* Encode PAC */ sp = krb5_storage_emem(); - if (sp == NULL) { - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; - } + if (sp == NULL) + return _krb5_enomem(context); + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); spdata = krb5_storage_emem(); if (spdata == NULL) { krb5_storage_free(sp); - krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); - return ENOMEM; + return _krb5_enomem(context); } krb5_storage_set_flags(spdata, KRB5_STORAGE_BYTEORDER_LE); @@ -1010,8 +1031,7 @@ _krb5_pac_sign(krb5_context context, sret = krb5_storage_write(spdata, ptr, len); if (sret != len) { - ret = ENOMEM; - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); + ret = _krb5_enomem(context); goto out; } /* XXX if not aligned, fill_zeros */ @@ -1048,15 +1068,14 @@ _krb5_pac_sign(krb5_context context, ret = krb5_storage_write(sp, d.data, d.length); if (ret != d.length) { krb5_data_free(&d); - ret = ENOMEM; - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); + ret = _krb5_enomem(context); goto out; } krb5_data_free(&d); ret = krb5_storage_to_data(sp, &d); if (ret) { - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); + ret = _krb5_enomem(context); goto out; } diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c index e19ba4a27c..89be46c1ae 100644 --- a/source4/heimdal/lib/krb5/plugin.c +++ b/source4/heimdal/lib/krb5/plugin.c @@ -336,3 +336,260 @@ _krb5_plugin_free(struct krb5_plugin *list) list = next; } } +/* + * module - dict of { + * ModuleName = [ + * plugin = object{ + * array = { ptr, ctx } + * } + * ] + * } + */ + +static heim_dict_t modules; + +struct plugin2 { + heim_string_t path; + void *dsohandle; + heim_dict_t names; +}; + +static void +plug_dealloc(void *ptr) +{ + struct plugin2 *p = ptr; + heim_release(p->path); + heim_release(p->names); + if (p->dsohandle) + dlclose(p->dsohandle); +} + + +void +_krb5_load_plugins(krb5_context context, const char *name, const char **paths) +{ +#ifdef HAVE_DLOPEN + heim_string_t s = heim_string_create(name); + heim_dict_t module; + struct dirent *entry; + krb5_error_code ret; + const char **di; + DIR *d; + + HEIMDAL_MUTEX_lock(&plugin_mutex); + + if (modules == NULL) { + modules = heim_dict_create(11); + if (modules == NULL) { + HEIMDAL_MUTEX_unlock(&plugin_mutex); + return; + } + } + + module = heim_dict_copy_value(modules, s); + if (module == NULL) { + module = heim_dict_create(11); + if (module == NULL) { + HEIMDAL_MUTEX_unlock(&plugin_mutex); + heim_release(s); + return; + } + heim_dict_add_value(modules, s, module); + } + heim_release(s); + + for (di = paths; *di != NULL; di++) { + d = opendir(*di); + if (d == NULL) + continue; + rk_cloexec_dir(d); + + while ((entry = readdir(d)) != NULL) { + char *n = entry->d_name; + char *path = NULL; + heim_string_t spath; + struct plugin2 *p; + + /* skip . and .. */ + if (n[0] == '.' && (n[1] == '\0' || (n[1] == '.' && n[2] == '\0'))) + continue; + + ret = 0; +#ifdef __APPLE__ + { /* support loading bundles on MacOS */ + size_t len = strlen(n); + if (len > 7 && strcmp(&n[len - 7], ".bundle") == 0) + ret = asprintf(&path, "%s/%s/Contents/MacOS/%.*s", *di, n, (int)(len - 7), n); + } +#endif + if (ret < 0 || path == NULL) + ret = asprintf(&path, "%s/%s", *di, n); + + if (ret < 0 || path == NULL) + continue; + + spath = heim_string_create(n); + if (spath == NULL) { + free(path); + continue; + } + + /* check if already cached */ + p = heim_dict_copy_value(module, spath); + if (p == NULL) { + p = heim_alloc(sizeof(*p), "krb5-plugin", plug_dealloc); + if (p) + p->dsohandle = dlopen(path, RTLD_LOCAL|RTLD_LAZY); + + if (p->dsohandle) { + p->path = heim_retain(spath); + p->names = heim_dict_create(11); + heim_dict_add_value(module, spath, p); + } + } + heim_release(spath); + heim_release(p); + free(path); + } + closedir(d); + } + heim_release(module); + HEIMDAL_MUTEX_unlock(&plugin_mutex); +#endif /* HAVE_DLOPEN */ +} + +void +_krb5_unload_plugins(krb5_context context, const char *name) +{ + HEIMDAL_MUTEX_lock(&plugin_mutex); + heim_release(modules); + modules = NULL; + HEIMDAL_MUTEX_unlock(&plugin_mutex); +} + +/* + * + */ + +struct common_plugin_method { + int version; + krb5_error_code (*init)(krb5_context, void **); + void (*fini)(void *); +}; + +struct plug { + void *dataptr; + void *ctx; +}; + +static void +plug_free(void *ptr) +{ + struct plug *pl = ptr; + if (pl->dataptr) { + struct common_plugin_method *cpm = pl->dataptr; + cpm->fini(pl->ctx); + } +} + +struct iter_ctx { + krb5_context context; + heim_string_t n; + const char *name; + int min_version; + heim_array_t result; + krb5_error_code (*func)(krb5_context, const void *, void *, void *); + void *userctx; + krb5_error_code ret; +}; + +static void +search_modules(void *ctx, heim_object_t key, heim_object_t value) +{ + struct iter_ctx *s = ctx; + struct plugin2 *p = value; + struct plug *pl = heim_dict_copy_value(p->names, s->n); + struct common_plugin_method *cpm; + + if (pl == NULL) { + if (p->dsohandle == NULL) + return; + + pl = heim_alloc(sizeof(*pl), "struct-plug", plug_free); + + cpm = pl->dataptr = dlsym(p->dsohandle, s->name); + if (cpm) { + int ret; + + ret = cpm->init(s->context, &pl->ctx); + if (ret) + cpm = pl->dataptr = NULL; + } + heim_dict_add_value(p->names, s->n, pl); + } else { + cpm = pl->dataptr; + } + + if (cpm && cpm->version >= s->min_version) + heim_array_append_value(s->result, pl); + + heim_release(pl); +} + +static void +eval_results(heim_object_t value, void *ctx) +{ + struct plug *pl = value; + struct iter_ctx *s = ctx; + + if (s->ret != KRB5_PLUGIN_NO_HANDLE) + return; + + s->ret = s->func(s->context, pl->dataptr, pl->ctx, s->userctx); +} + +krb5_error_code +_krb5_plugin_run_f(krb5_context context, + const char *module, + const char *name, + int min_version, + int flags, + void *userctx, + krb5_error_code (*func)(krb5_context, const void *, void *, void *)) +{ + heim_string_t m = heim_string_create(module); + heim_dict_t dict; + struct iter_ctx s; + + HEIMDAL_MUTEX_lock(&plugin_mutex); + + dict = heim_dict_copy_value(modules, m); + heim_release(m); + if (dict == NULL) { + HEIMDAL_MUTEX_unlock(&plugin_mutex); + return KRB5_PLUGIN_NO_HANDLE; + } + + s.context = context; + s.name = name; + s.n = heim_string_create(name); + s.min_version = min_version; + s.result = heim_array_create(); + s.func = func; + s.userctx = userctx; + + heim_dict_iterate_f(dict, search_modules, &s); + + heim_release(dict); + + HEIMDAL_MUTEX_unlock(&plugin_mutex); + + s.ret = KRB5_PLUGIN_NO_HANDLE; + + heim_array_iterate_f(s.result, eval_results, &s); + + heim_release(s.result); + heim_release(s.n); + + return s.ret; +} diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index 49e68ef177..0dedba3d72 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -222,30 +222,6 @@ krb5_storage_get_eof_code(krb5_storage *sp) return sp->eof_code; } -KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL -_krb5_put_int(void *buffer, unsigned long value, size_t size) -{ - unsigned char *p = buffer; - int i; - for (i = size - 1; i >= 0; i--) { - p[i] = value & 0xff; - value >>= 8; - } - return size; -} - -KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL -_krb5_get_int(void *buffer, unsigned long *value, size_t size) -{ - unsigned char *p = buffer; - unsigned long v = 0; - int i; - for (i = 0; i < size; i++) - v = (v << 8) + p[i]; - *value = v; - return size; -} - /** * Free a krb5 storage. * diff --git a/source4/heimdal/lib/ntlm/heimntlm.h b/source4/heimdal/lib/ntlm/heimntlm.h index 0fcc832e1f..22e2142df8 100644 --- a/source4/heimdal/lib/ntlm/heimntlm.h +++ b/source4/heimdal/lib/ntlm/heimntlm.h @@ -46,14 +46,16 @@ struct ntlm_buf { }; #define NTLM_NEG_UNICODE 0x00000001 -#define NTLM_NEG_OEM 0x00000002 +#define NTLM_NEG_OEM 0x00000002 #define NTLM_NEG_TARGET 0x00000004 #define NTLM_MBZ9 0x00000008 #define NTLM_NEG_SIGN 0x00000010 #define NTLM_NEG_SEAL 0x00000020 -#define NTLM_NEG_DATAGRAM 0x00000040 -#define NTLM_NEG_LM_KEY 0x00000080 +#define NTLM_NEG_DATAGRAM 0x00000040 +#define NTLM_NEG_LM_KEY 0x00000080 +#define NTLM_NEG_NTLM 0x00000200 +#define NTLM_NEG_ANONYMOUS 0x00000800 #define NTLM_MBZ8 0x00000100 #define NTLM_NEG_NTLM 0x00000200 @@ -61,12 +63,13 @@ struct ntlm_buf { #define NTLM_MBZ7 0x00000800 /* anon ? */ #define NTLM_OEM_SUPPLIED_DOMAIN 0x00001000 -#define NTLM_OEM_SUPPLIED_WORKSTAION 0x00002000 +#define NTLM_OEM_SUPPLIED_WORKSTATION 0x00002000 #define NTLM_MBZ6 0x00004000 /* local call ? */ #define NTLM_NEG_ALWAYS_SIGN 0x00008000 #define NTLM_TARGET_DOMAIN 0x00010000 #define NTLM_TARGET_SERVER 0x00020000 + #define NTLM_TARGET_SHARE 0x00040000 #define NTLM_NEG_NTLM2_SESSION 0x00080000 #define NTLM_NEG_NTLM2 0x00080000 @@ -84,18 +87,23 @@ struct ntlm_buf { #define NTLM_MBZ1 0x10000000 #define NTLM_ENC_128 0x20000000 #define NTLM_NEG_KEYEX 0x40000000 -#define NTLM_NEGOTIATE_56 0x80000000 +#define NTLM_ENC_56 0x80000000 /** * Struct for the NTLM target info, the strings is assumed to be in * UTF8. When filled in by the library it should be freed with * heim_ntlm_free_targetinfo(). */ + +#define NTLM_TI_AV_FLAG_GUEST 0x00000001 + struct ntlm_targetinfo { char *servername; /**< */ char *domainname; /**< */ char *dnsdomainname; /**< */ char *dnsservername; /**< */ + char *dnstreename; /**< */ + uint32_t avflags; /**< */ }; /** @@ -121,7 +129,7 @@ struct ntlm_type2 { uint32_t flags; /**< */ char *targetname; /**< */ struct ntlm_buf targetinfo; /**< */ - unsigned char challange[8]; /**< */ + unsigned char challenge[8]; /**< */ uint32_t context[2]; /**< */ uint32_t os[2]; /**< */ }; @@ -143,6 +151,7 @@ struct ntlm_type3 { uint32_t os[2]; /**< */ }; +#include #include #endif /* NTLM_NTLM_H */ diff --git a/source4/heimdal/lib/ntlm/ntlm.c b/source4/heimdal/lib/ntlm/ntlm.c index 8390d79acc..1cc5c06445 100644 --- a/source4/heimdal/lib/ntlm/ntlm.c +++ b/source4/heimdal/lib/ntlm/ntlm.c @@ -3,6 +3,8 @@ * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -42,6 +44,7 @@ #include #include +#include #include #define HC_DEPRECATED_CRYPTO @@ -105,7 +108,54 @@ static const unsigned char ntlmsigature[8] = "NTLMSSP\x00"; */ #define CHECK(f, e) \ - do { ret = f ; if (ret != (e)) { ret = EINVAL; goto out; } } while(0) + do { \ + ret = f ; if (ret != (e)) { ret = HNTLM_ERR_DECODE; goto out; } } \ + while(0) + +static struct units ntlm_flag_units[] = { +#define ntlm_flag(x) { #x, NTLM_##x } + ntlm_flag(ENC_56), + ntlm_flag(NEG_KEYEX), + ntlm_flag(ENC_128), + ntlm_flag(MBZ1), + ntlm_flag(MBZ2), + ntlm_flag(MBZ3), + ntlm_flag(NEG_VERSION), + ntlm_flag(MBZ4), + ntlm_flag(NEG_TARGET_INFO), + ntlm_flag(NON_NT_SESSION_KEY), + ntlm_flag(MBZ5), + ntlm_flag(NEG_IDENTIFY), + ntlm_flag(NEG_NTLM2), + ntlm_flag(TARGET_SHARE), + ntlm_flag(TARGET_SERVER), + ntlm_flag(TARGET_DOMAIN), + ntlm_flag(NEG_ALWAYS_SIGN), + ntlm_flag(MBZ6), + ntlm_flag(OEM_SUPPLIED_WORKSTATION), + ntlm_flag(OEM_SUPPLIED_DOMAIN), + ntlm_flag(NEG_ANONYMOUS), + ntlm_flag(NEG_NT_ONLY), + ntlm_flag(NEG_NTLM), + ntlm_flag(MBZ8), + ntlm_flag(NEG_LM_KEY), + ntlm_flag(NEG_DATAGRAM), + ntlm_flag(NEG_SEAL), + ntlm_flag(NEG_SIGN), + ntlm_flag(MBZ9), + ntlm_flag(NEG_TARGET), + ntlm_flag(NEG_OEM), + ntlm_flag(NEG_UNICODE), +#undef ntlm_flag + {NULL, 0} +}; + +size_t +heim_ntlm_unparse_flags(uint32_t flags, char *s, size_t len) +{ + return unparse_flags(flags, ntlm_flag_units, s, len); +} + /** * heim_ntlm_free_buf frees the ntlm buffer @@ -197,19 +247,25 @@ len_string(int ucs2, const char *s) return len; } +/* + * + */ + static krb5_error_code -ret_string(krb5_storage *sp, int ucs2, struct sec_buffer *desc, char **s) +ret_string(krb5_storage *sp, int ucs2, size_t len, char **s) { krb5_error_code ret; - *s = malloc(desc->length + 1); - CHECK(krb5_storage_seek(sp, desc->offset, SEEK_SET), desc->offset); - CHECK(krb5_storage_read(sp, *s, desc->length), desc->length); - (*s)[desc->length] = '\0'; + *s = malloc(len + 1); + if (*s == NULL) + return ENOMEM; + CHECK(krb5_storage_read(sp, *s, len), len); + + (*s)[len] = '\0'; if (ucs2) { size_t i; - for (i = 0; i < desc->length / 2; i++) { + for (i = 0; i < len / 2; i++) { (*s)[i] = (*s)[i * 2]; if ((*s)[i * 2 + 1]) { free(*s); @@ -220,7 +276,19 @@ ret_string(krb5_storage *sp, int ucs2, struct sec_buffer *desc, char **s) (*s)[i] = '\0'; } ret = 0; -out: + out: + return ret; +} + + + +static krb5_error_code +ret_sec_string(krb5_storage *sp, int ucs2, struct sec_buffer *desc, char **s) +{ + krb5_error_code ret = 0; + CHECK(krb5_storage_seek(sp, desc->offset, SEEK_SET), desc->offset); + CHECK(ret_string(sp, ucs2, desc->length, s), 0); + out: return ret; } @@ -290,11 +358,12 @@ heim_ntlm_free_targetinfo(struct ntlm_targetinfo *ti) free(ti->domainname); free(ti->dnsdomainname); free(ti->dnsservername); + free(ti->dnstreename); memset(ti, 0, sizeof(*ti)); } static int -encode_ti_blob(krb5_storage *out, uint16_t type, int ucs2, char *s) +encode_ti_string(krb5_storage *out, uint16_t type, int ucs2, char *s) { krb5_error_code ret; CHECK(krb5_store_uint16(out, type), 0); @@ -308,7 +377,7 @@ out: * Encodes a ntlm_targetinfo message. * * @param ti the ntlm_targetinfo message to encode. - * @param ucs2 if the strings should be encoded with ucs2 (selected by flag in message). + * @param ucs2 ignored * @param data is the return buffer with the encoded message, should be * freed with heim_ntlm_free_buf(). * @@ -333,14 +402,23 @@ heim_ntlm_encode_targetinfo(const struct ntlm_targetinfo *ti, if (out == NULL) return ENOMEM; + krb5_storage_set_byteorder(out, KRB5_STORAGE_BYTEORDER_LE); + if (ti->servername) - CHECK(encode_ti_blob(out, 1, ucs2, ti->servername), 0); + CHECK(encode_ti_string(out, 1, ucs2, ti->servername), 0); if (ti->domainname) - CHECK(encode_ti_blob(out, 2, ucs2, ti->domainname), 0); + CHECK(encode_ti_string(out, 2, ucs2, ti->domainname), 0); if (ti->dnsservername) - CHECK(encode_ti_blob(out, 3, ucs2, ti->dnsservername), 0); + CHECK(encode_ti_string(out, 3, ucs2, ti->dnsservername), 0); if (ti->dnsdomainname) - CHECK(encode_ti_blob(out, 4, ucs2, ti->dnsdomainname), 0); + CHECK(encode_ti_string(out, 4, ucs2, ti->dnsdomainname), 0); + if (ti->dnstreename) + CHECK(encode_ti_string(out, 5, ucs2, ti->dnstreename), 0); + if (ti->avflags) { + CHECK(krb5_store_uint16(out, 6), 0); + CHECK(krb5_store_uint16(out, 4), 0); + CHECK(krb5_store_uint32(out, ti->avflags), 0); + } /* end tag */ CHECK(krb5_store_int16(out, 0), 0); @@ -375,8 +453,55 @@ heim_ntlm_decode_targetinfo(const struct ntlm_buf *data, int ucs2, struct ntlm_targetinfo *ti) { + uint16_t type, len; + krb5_storage *in; + int ret, done = 0; + memset(ti, 0, sizeof(*ti)); - return 0; + + if (data->length == 0) + return 0; + + in = krb5_storage_from_readonly_mem(data->data, data->length); + if (in == NULL) + return ENOMEM; + krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE); + + while (!done) { + CHECK(krb5_ret_uint16(in, &type), 0); + CHECK(krb5_ret_uint16(in, &len), 0); + + switch (type) { + case 0: + done = 1; + break; + case 1: + CHECK(ret_string(in, ucs2, len, &ti->servername), 0); + break; + case 2: + CHECK(ret_string(in, ucs2, len, &ti->domainname), 0); + break; + case 3: + CHECK(ret_string(in, ucs2, len, &ti->dnsservername), 0); + break; + case 4: + CHECK(ret_string(in, ucs2, len, &ti->dnsdomainname), 0); + break; + case 5: + CHECK(ret_string(in, ucs2, len, &ti->dnstreename), 0); + break; + case 6: + CHECK(krb5_ret_uint32(in, &ti->avflags), 0); + break; + default: + krb5_storage_seek(in, len, SEEK_CUR); + break; + } + } + out: + if (in) + krb5_storage_free(in); + return ret; } /** @@ -410,7 +535,7 @@ heim_ntlm_decode_type1(const struct ntlm_buf *buf, struct ntlm_type1 *data) in = krb5_storage_from_readonly_mem(buf->data, buf->length); if (in == NULL) { - ret = EINVAL; + ret = ENOMEM; goto out; } krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE); @@ -422,7 +547,7 @@ heim_ntlm_decode_type1(const struct ntlm_buf *buf, struct ntlm_type1 *data) CHECK(krb5_ret_uint32(in, &data->flags), 0); if (data->flags & NTLM_OEM_SUPPLIED_DOMAIN) CHECK(ret_sec_buffer(in, &domain), 0); - if (data->flags & NTLM_OEM_SUPPLIED_WORKSTAION) + if (data->flags & NTLM_OEM_SUPPLIED_WORKSTATION) CHECK(ret_sec_buffer(in, &hostname), 0); #if 0 if (domain.offset > 32) { @@ -431,9 +556,9 @@ heim_ntlm_decode_type1(const struct ntlm_buf *buf, struct ntlm_type1 *data) } #endif if (data->flags & NTLM_OEM_SUPPLIED_DOMAIN) - CHECK(ret_string(in, 0, &domain, &data->domain), 0); - if (data->flags & NTLM_OEM_SUPPLIED_WORKSTAION) - CHECK(ret_string(in, 0, &hostname, &data->hostname), 0); + CHECK(ret_sec_string(in, 0, &domain, &data->domain), 0); + if (data->flags & NTLM_OEM_SUPPLIED_WORKSTATION) + CHECK(ret_sec_string(in, 0, &hostname, &data->hostname), 0); out: if (in) @@ -474,24 +599,27 @@ heim_ntlm_encode_type1(const struct ntlm_type1 *type1, struct ntlm_buf *data) } if (type1->hostname) { base += 8; - flags |= NTLM_OEM_SUPPLIED_WORKSTAION; + flags |= NTLM_OEM_SUPPLIED_WORKSTATION; } if (type1->os[0]) base += 8; + domain.offset = base; if (type1->domain) { - domain.offset = base; domain.length = len_string(0, type1->domain); domain.allocated = domain.length; } else { - domain.offset = 0; domain.length = 0; domain.allocated = 0; } + + hostname.offset = domain.allocated + domain.offset; if (type1->hostname) { - hostname.offset = domain.allocated + domain.offset; hostname.length = len_string(0, type1->hostname); hostname.allocated = hostname.length; + } else { + hostname.length = 0; + hostname.allocated = 0; } out = krb5_storage_emem(); @@ -504,14 +632,12 @@ heim_ntlm_encode_type1(const struct ntlm_type1 *type1, struct ntlm_buf *data) CHECK(krb5_store_uint32(out, 1), 0); CHECK(krb5_store_uint32(out, flags), 0); - if (type1->domain) - CHECK(store_sec_buffer(out, &domain), 0); - if (type1->hostname) - CHECK(store_sec_buffer(out, &hostname), 0); - if (type1->os[0]) { + CHECK(store_sec_buffer(out, &domain), 0); + CHECK(store_sec_buffer(out, &hostname), 0); +#if 0 CHECK(krb5_store_uint32(out, type1->os[0]), 0); CHECK(krb5_store_uint32(out, type1->os[1]), 0); - } +#endif if (type1->domain) CHECK(put_string(out, 0, type1->domain), 0); if (type1->hostname) @@ -560,7 +686,7 @@ heim_ntlm_decode_type2(const struct ntlm_buf *buf, struct ntlm_type2 *type2) in = krb5_storage_from_readonly_mem(buf->data, buf->length); if (in == NULL) { - ret = EINVAL; + ret = ENOMEM; goto out; } krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE); @@ -574,18 +700,18 @@ heim_ntlm_decode_type2(const struct ntlm_buf *buf, struct ntlm_type2 *type2) CHECK(krb5_ret_uint32(in, &type2->flags), 0); if (type2->flags & NTLM_NEG_UNICODE) ucs2 = 1; - CHECK(krb5_storage_read(in, type2->challange, sizeof(type2->challange)), - sizeof(type2->challange)); + CHECK(krb5_storage_read(in, type2->challenge, sizeof(type2->challenge)), + sizeof(type2->challenge)); CHECK(krb5_ret_uint32(in, &ctx[0]), 0); /* context */ CHECK(krb5_ret_uint32(in, &ctx[1]), 0); CHECK(ret_sec_buffer(in, &targetinfo), 0); /* os version */ -#if 0 - CHECK(krb5_ret_uint32(in, &type2->os[0]), 0); - CHECK(krb5_ret_uint32(in, &type2->os[1]), 0); -#endif + if (type2->flags & NTLM_NEG_VERSION) { + CHECK(krb5_ret_uint32(in, &type2->os[0]), 0); + CHECK(krb5_ret_uint32(in, &type2->os[1]), 0); + } - CHECK(ret_string(in, ucs2, &targetname, &type2->targetname), 0); + CHECK(ret_sec_string(in, ucs2, &targetname, &type2->targetname), 0); CHECK(ret_buf(in, &targetinfo, &type2->targetinfo), 0); ret = 0; @@ -620,10 +746,10 @@ heim_ntlm_encode_type2(const struct ntlm_type2 *type2, struct ntlm_buf *data) uint32_t base; int ucs2 = 0; - if (type2->os[0]) - base = 56; - else - base = 48; + base = 48; + + if (type2->flags & NTLM_NEG_VERSION) + base += 8; if (type2->flags & NTLM_NEG_UNICODE) ucs2 = 1; @@ -646,13 +772,13 @@ heim_ntlm_encode_type2(const struct ntlm_type2 *type2, struct ntlm_buf *data) CHECK(krb5_store_uint32(out, 2), 0); CHECK(store_sec_buffer(out, &targetname), 0); CHECK(krb5_store_uint32(out, type2->flags), 0); - CHECK(krb5_storage_write(out, type2->challange, sizeof(type2->challange)), - sizeof(type2->challange)); + CHECK(krb5_storage_write(out, type2->challenge, sizeof(type2->challenge)), + sizeof(type2->challenge)); CHECK(krb5_store_uint32(out, 0), 0); /* context */ CHECK(krb5_store_uint32(out, 0), 0); CHECK(store_sec_buffer(out, &targetinfo), 0); /* os version */ - if (type2->os[0]) { + if (type2->flags & NTLM_NEG_VERSION) { CHECK(krb5_store_uint32(out, type2->os[0]), 0); CHECK(krb5_store_uint32(out, type2->os[1]), 0); } @@ -711,13 +837,14 @@ heim_ntlm_decode_type3(const struct ntlm_buf *buf, uint32_t type; krb5_storage *in; struct sec_buffer lm, ntlm, target, username, sessionkey, ws; + uint32_t min_offset = 72; memset(type3, 0, sizeof(*type3)); memset(&sessionkey, 0, sizeof(sessionkey)); in = krb5_storage_from_readonly_mem(buf->data, buf->length); if (in == NULL) { - ret = EINVAL; + ret = ENOMEM; goto out; } krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE); @@ -727,25 +854,35 @@ heim_ntlm_decode_type3(const struct ntlm_buf *buf, CHECK(krb5_ret_uint32(in, &type), 0); CHECK(type, 3); CHECK(ret_sec_buffer(in, &lm), 0); + if (lm.allocated) + min_offset = MIN(min_offset, lm.offset); CHECK(ret_sec_buffer(in, &ntlm), 0); + if (ntlm.allocated) + min_offset = MIN(min_offset, ntlm.offset); CHECK(ret_sec_buffer(in, &target), 0); + if (target.allocated) + min_offset = MIN(min_offset, target.offset); CHECK(ret_sec_buffer(in, &username), 0); + if (username.allocated) + min_offset = MIN(min_offset, username.offset); CHECK(ret_sec_buffer(in, &ws), 0); - if (lm.offset >= 60) { + if (ws.allocated) + min_offset = MIN(min_offset, ws.offset); + + if (min_offset > 52) { CHECK(ret_sec_buffer(in, &sessionkey), 0); - } - if (lm.offset >= 64) { + min_offset = MAX(min_offset, sessionkey.offset); CHECK(krb5_ret_uint32(in, &type3->flags), 0); } - if (lm.offset >= 72) { + if (min_offset > 52 + 8 + 4 + 8) { CHECK(krb5_ret_uint32(in, &type3->os[0]), 0); CHECK(krb5_ret_uint32(in, &type3->os[1]), 0); } CHECK(ret_buf(in, &lm, &type3->lm), 0); CHECK(ret_buf(in, &ntlm, &type3->ntlm), 0); - CHECK(ret_string(in, ucs2, &target, &type3->targetname), 0); - CHECK(ret_string(in, ucs2, &username, &type3->username), 0); - CHECK(ret_string(in, ucs2, &ws, &type3->ws), 0); + CHECK(ret_sec_string(in, ucs2, &target, &type3->targetname), 0); + CHECK(ret_sec_string(in, ucs2, &username, &type3->username), 0); + CHECK(ret_sec_string(in, ucs2, &ws, &type3->ws), 0); if (sessionkey.offset) CHECK(ret_buf(in, &sessionkey, &type3->sessionkey), 0); @@ -788,10 +925,10 @@ heim_ntlm_encode_type3(const struct ntlm_type3 *type3, struct ntlm_buf *data) memset(&sessionkey, 0, sizeof(sessionkey)); base = 52; - if (type3->sessionkey.length) { - base += 8; /* sessionkey sec buf */ - base += 4; /* flags */ - } + + base += 8; /* sessionkey sec buf */ + base += 4; /* flags */ + if (type3->os[0]) { base += 8; } @@ -799,15 +936,7 @@ heim_ntlm_encode_type3(const struct ntlm_type3 *type3, struct ntlm_buf *data) if (type3->flags & NTLM_NEG_UNICODE) ucs2 = 1; - lm.offset = base; - lm.length = type3->lm.length; - lm.allocated = type3->lm.length; - - ntlm.offset = lm.offset + lm.allocated; - ntlm.length = type3->ntlm.length; - ntlm.allocated = ntlm.length; - - target.offset = ntlm.offset + ntlm.allocated; + target.offset = base; target.length = len_string(ucs2, type3->targetname); target.allocated = target.length; @@ -819,7 +948,15 @@ heim_ntlm_encode_type3(const struct ntlm_type3 *type3, struct ntlm_buf *data) ws.length = len_string(ucs2, type3->ws); ws.allocated = ws.length; - sessionkey.offset = ws.offset + ws.allocated; + lm.offset = ws.offset + ws.allocated; + lm.length = type3->lm.length; + lm.allocated = type3->lm.length; + + ntlm.offset = lm.offset + lm.allocated; + ntlm.length = type3->ntlm.length; + ntlm.allocated = ntlm.length; + + sessionkey.offset = ntlm.offset + ntlm.allocated; sessionkey.length = type3->sessionkey.length; sessionkey.allocated = type3->sessionkey.length; @@ -837,21 +974,19 @@ heim_ntlm_encode_type3(const struct ntlm_type3 *type3, struct ntlm_buf *data) CHECK(store_sec_buffer(out, &target), 0); CHECK(store_sec_buffer(out, &username), 0); CHECK(store_sec_buffer(out, &ws), 0); - /* optional */ - if (type3->sessionkey.length) { - CHECK(store_sec_buffer(out, &sessionkey), 0); - CHECK(krb5_store_uint32(out, type3->flags), 0); - } + CHECK(store_sec_buffer(out, &sessionkey), 0); + CHECK(krb5_store_uint32(out, type3->flags), 0); + #if 0 CHECK(krb5_store_uint32(out, 0), 0); /* os0 */ CHECK(krb5_store_uint32(out, 0), 0); /* os1 */ #endif - CHECK(put_buf(out, &type3->lm), 0); - CHECK(put_buf(out, &type3->ntlm), 0); CHECK(put_string(out, ucs2, type3->targetname), 0); CHECK(put_string(out, ucs2, type3->username), 0); CHECK(put_string(out, ucs2, type3->ws), 0); + CHECK(put_buf(out, &type3->lm), 0); + CHECK(put_buf(out, &type3->ntlm), 0); CHECK(put_buf(out, &type3->sessionkey), 0); { @@ -874,7 +1009,7 @@ out: static void splitandenc(unsigned char *hash, - unsigned char *challange, + unsigned char *challenge, unsigned char *answer) { EVP_CIPHER_CTX ctx; @@ -892,7 +1027,7 @@ splitandenc(unsigned char *hash, EVP_CIPHER_CTX_init(&ctx); EVP_CipherInit_ex(&ctx, EVP_des_cbc(), NULL, key, NULL, 1); - EVP_Cipher(&ctx, answer, challange, 8); + EVP_Cipher(&ctx, answer, challenge, 8); EVP_CIPHER_CTX_cleanup(&ctx); memset(key, 0, sizeof(key)); } @@ -948,7 +1083,7 @@ heim_ntlm_nt_key(const char *password, struct ntlm_buf *key) * * @param key the ntlm v1 key * @param len length of key - * @param challange sent by the server + * @param challenge sent by the server * @param answer calculated answer, should be freed with heim_ntlm_free_buf(). * * @return In case of success 0 is return, an errors, a errno in what @@ -959,13 +1094,13 @@ heim_ntlm_nt_key(const char *password, struct ntlm_buf *key) int heim_ntlm_calculate_ntlm1(void *key, size_t len, - unsigned char challange[8], + unsigned char challenge[8], struct ntlm_buf *answer) { unsigned char res[21]; if (len != MD4_DIGEST_LENGTH) - return EINVAL; + return HNTLM_ERR_INVALID_LENGTH; memcpy(res, key, len); memset(&res[MD4_DIGEST_LENGTH], 0, sizeof(res) - MD4_DIGEST_LENGTH); @@ -975,13 +1110,116 @@ heim_ntlm_calculate_ntlm1(void *key, size_t len, return ENOMEM; answer->length = 24; - splitandenc(&res[0], challange, ((unsigned char *)answer->data) + 0); - splitandenc(&res[7], challange, ((unsigned char *)answer->data) + 8); - splitandenc(&res[14], challange, ((unsigned char *)answer->data) + 16); + splitandenc(&res[0], challenge, ((unsigned char *)answer->data) + 0); + splitandenc(&res[7], challenge, ((unsigned char *)answer->data) + 8); + splitandenc(&res[14], challenge, ((unsigned char *)answer->data) + 16); + + return 0; +} + +int +heim_ntlm_v1_base_session(void *key, size_t len, + struct ntlm_buf *session) +{ + EVP_MD_CTX *m; + + session->length = MD4_DIGEST_LENGTH; + session->data = malloc(session->length); + if (session->data == NULL) { + session->length = 0; + return ENOMEM; + } + + m = EVP_MD_CTX_create(); + if (m == NULL) { + heim_ntlm_free_buf(session); + return ENOMEM; + } + EVP_DigestInit_ex(m, EVP_md4(), NULL); + EVP_DigestUpdate(m, key, len); + EVP_DigestFinal_ex(m, session->data, NULL); + EVP_MD_CTX_destroy(m); + + return 0; +} + +int +heim_ntlm_v2_base_session(void *key, size_t len, + struct ntlm_buf *ntlmResponse, + struct ntlm_buf *session) +{ + unsigned int hmaclen; + HMAC_CTX c; + + if (ntlmResponse->length <= 16) + return HNTLM_ERR_INVALID_LENGTH; + + session->data = malloc(16); + if (session->data == NULL) + return ENOMEM; + session->length = 16; + + /* Note: key is the NTLMv2 key */ + HMAC_CTX_init(&c); + HMAC_Init_ex(&c, key, len, EVP_md5(), NULL); + HMAC_Update(&c, ntlmResponse->data, 16); + HMAC_Final(&c, session->data, &hmaclen); + HMAC_CTX_cleanup(&c); + + return 0; +} + + +int +heim_ntlm_keyex_wrap(struct ntlm_buf *base_session, + struct ntlm_buf *session, + struct ntlm_buf *encryptedSession) +{ + EVP_CIPHER_CTX c; + int ret; + + session->length = MD4_DIGEST_LENGTH; + session->data = malloc(session->length); + if (session->data == NULL) { + session->length = 0; + return ENOMEM; + } + encryptedSession->length = MD4_DIGEST_LENGTH; + encryptedSession->data = malloc(encryptedSession->length); + if (encryptedSession->data == NULL) { + heim_ntlm_free_buf(session); + encryptedSession->length = 0; + return ENOMEM; + } + + EVP_CIPHER_CTX_init(&c); + + ret = EVP_CipherInit_ex(&c, EVP_rc4(), NULL, base_session->data, NULL, 1); + if (ret != 1) { + EVP_CIPHER_CTX_cleanup(&c); + heim_ntlm_free_buf(encryptedSession); + heim_ntlm_free_buf(session); + return HNTLM_ERR_CRYPTO; + } + + if (RAND_bytes(session->data, session->length) != 1) { + EVP_CIPHER_CTX_cleanup(&c); + heim_ntlm_free_buf(encryptedSession); + heim_ntlm_free_buf(session); + return HNTLM_ERR_RAND; + } + + EVP_Cipher(&c, encryptedSession->data, session->data, encryptedSession->length); + EVP_CIPHER_CTX_cleanup(&c); return 0; + + + } + + /** * Generates an NTLMv1 session random with assosited session master key. * @@ -1000,69 +1238,102 @@ int heim_ntlm_build_ntlm1_master(void *key, size_t len, struct ntlm_buf *session, struct ntlm_buf *master) +{ + struct ntlm_buf sess; + int ret; + + ret = heim_ntlm_v1_base_session(key, len, &sess); + if (ret) + return ret; + + ret = heim_ntlm_keyex_wrap(&sess, session, master); + heim_ntlm_free_buf(&sess); + + return ret; +} + +/** + * Generates an NTLMv2 session random with associated session master key. + * + * @param key the NTLMv2 key + * @param len length of key + * @param blob the NTLMv2 "blob" + * @param session generated session nonce, should be freed with heim_ntlm_free_buf(). + * @param master calculated session master key, should be freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core + */ + + +int +heim_ntlm_build_ntlm2_master(void *key, size_t len, + struct ntlm_buf *blob, + struct ntlm_buf *session, + struct ntlm_buf *master) +{ + struct ntlm_buf sess; + int ret; + + ret = heim_ntlm_v2_base_session(key, len, blob, &sess); + if (ret) + return ret; + + ret = heim_ntlm_keyex_wrap(&sess, session, master); + heim_ntlm_free_buf(&sess); + + return ret; +} + +/** + * Given a key and encrypted session, unwrap the session key + * + * @param key the sessionBaseKey + * @param len length of key + * @param encryptedSession encrypted session, type3.session field. + * @param session generated session nonce, should be freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core + */ + +int +heim_ntlm_keyex_unwrap(struct ntlm_buf *baseKey, + struct ntlm_buf *encryptedSession, + struct ntlm_buf *session) { EVP_CIPHER_CTX c; - memset(master, 0, sizeof(*master)); memset(session, 0, sizeof(*session)); - if (len != MD4_DIGEST_LENGTH) - return EINVAL; + if (baseKey->length != MD4_DIGEST_LENGTH) + return HNTLM_ERR_INVALID_LENGTH; session->length = MD4_DIGEST_LENGTH; session->data = malloc(session->length); if (session->data == NULL) { session->length = 0; - return EINVAL; - } - master->length = MD4_DIGEST_LENGTH; - master->data = malloc(master->length); - if (master->data == NULL) { - heim_ntlm_free_buf(master); - heim_ntlm_free_buf(session); - return EINVAL; + return ENOMEM; } - EVP_CIPHER_CTX_init(&c); - { - unsigned char sessionkey[MD4_DIGEST_LENGTH]; - EVP_MD_CTX *m; - - m = EVP_MD_CTX_create(); - if (m == NULL) { - EVP_CIPHER_CTX_cleanup(&c); - heim_ntlm_free_buf(master); - heim_ntlm_free_buf(session); - return ENOMEM; - } - - EVP_DigestInit_ex(m, EVP_md4(), NULL); - EVP_DigestUpdate(m, key, len); - EVP_DigestFinal_ex(m, sessionkey, NULL); - EVP_MD_CTX_destroy(m); - - if (EVP_CipherInit_ex(&c, EVP_rc4(), NULL, sessionkey, NULL, 1) != 1) { - EVP_CIPHER_CTX_cleanup(&c); - heim_ntlm_free_buf(master); - heim_ntlm_free_buf(session); - return EINVAL; - } - } - - if (RAND_bytes(session->data, session->length) != 1) { + if (EVP_CipherInit_ex(&c, EVP_rc4(), NULL, baseKey->data, NULL, 0) != 1) { EVP_CIPHER_CTX_cleanup(&c); - heim_ntlm_free_buf(master); heim_ntlm_free_buf(session); - return EINVAL; + return HNTLM_ERR_CRYPTO; } - EVP_Cipher(&c, master->data, session->data, master->length); + EVP_Cipher(&c, session->data, encryptedSession->data, session->length); EVP_CIPHER_CTX_cleanup(&c); return 0; } + /** * Generates an NTLMv2 session key. * @@ -1134,6 +1405,54 @@ nt2unixtime(uint64_t t) return (time_t)t; } +/** + * Calculate LMv2 response + * + * @param key the ntlm key + * @param len length of key + * @param username name of the user, as sent in the message, assumed to be in UTF8. + * @param target the name of the target, assumed to be in UTF8. + * @param serverchallenge challenge as sent by the server in the type2 message. + * @param infotarget infotarget as sent by the server in the type2 message. + * @param ntlmv2 calculated session key + * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf(). + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core + */ + +int +heim_ntlm_calculate_lm2(const void *key, size_t len, + const char *username, + const char *target, + const unsigned char serverchallenge[8], + unsigned char ntlmv2[16], + struct ntlm_buf *answer) +{ + unsigned char clientchallenge[8]; + + if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1) + return HNTLM_ERR_RAND; + + /* calculate ntlmv2 key */ + + heim_ntlm_ntlmv2_key(key, len, username, target, ntlmv2); + + answer->data = malloc(24); + if (answer->data == NULL) + return ENOMEM; + answer->length = 24; + + heim_ntlm_derive_ntlm2_sess(ntlmv2, clientchallenge, 8, + serverchallenge, answer->data); + + memcpy(((uint8_t *)answer->data) + 16, clientchallenge, 8); + + return 0; +} + /** * Calculate NTLMv2 response @@ -1142,7 +1461,7 @@ nt2unixtime(uint64_t t) * @param len length of key * @param username name of the user, as sent in the message, assumed to be in UTF8. * @param target the name of the target, assumed to be in UTF8. - * @param serverchallange challange as sent by the server in the type2 message. + * @param serverchallenge challenge as sent by the server in the type2 message. * @param infotarget infotarget as sent by the server in the type2 message. * @param ntlmv2 calculated session key * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf(). @@ -1157,24 +1476,22 @@ int heim_ntlm_calculate_ntlm2(const void *key, size_t len, const char *username, const char *target, - const unsigned char serverchallange[8], + const unsigned char serverchallenge[8], const struct ntlm_buf *infotarget, unsigned char ntlmv2[16], struct ntlm_buf *answer) { krb5_error_code ret; krb5_data data; - unsigned int hmaclen; unsigned char ntlmv2answer[16]; krb5_storage *sp; - unsigned char clientchallange[8]; - HMAC_CTX c; + unsigned char clientchallenge[8]; uint64_t t; t = unix2nttime(time(NULL)); - if (RAND_bytes(clientchallange, sizeof(clientchallange)) != 1) - return EINVAL; + if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1) + return HNTLM_ERR_RAND; /* calculate ntlmv2 key */ @@ -1193,7 +1510,7 @@ heim_ntlm_calculate_ntlm2(const void *key, size_t len, CHECK(krb5_store_uint32(sp, t & 0xffffffff), 0); CHECK(krb5_store_uint32(sp, t >> 32), 0); - CHECK(krb5_storage_write(sp, clientchallange, 8), 8); + CHECK(krb5_storage_write(sp, clientchallenge, 8), 8); CHECK(krb5_store_uint32(sp, 0), 0); /* unknown but zero will work */ CHECK(krb5_storage_write(sp, infotarget->data, infotarget->length), @@ -1204,12 +1521,7 @@ heim_ntlm_calculate_ntlm2(const void *key, size_t len, krb5_storage_free(sp); sp = NULL; - HMAC_CTX_init(&c); - HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL); - HMAC_Update(&c, serverchallange, 8); - HMAC_Update(&c, data.data, data.length); - HMAC_Final(&c, ntlmv2answer, &hmaclen); - HMAC_CTX_cleanup(&c); + heim_ntlm_derive_ntlm2_sess(ntlmv2, data.data, data.length, serverchallenge, ntlmv2answer); sp = krb5_storage_emem(); if (sp == NULL) { @@ -1245,7 +1557,7 @@ static const int authtimediff = 3600 * 2; /* 2 hours */ * @param username name of the user, as sent in the message, assumed to be in UTF8. * @param target the name of the target, assumed to be in UTF8. * @param now the time now (0 if the library should pick it up itself) - * @param serverchallange challange as sent by the server in the type2 message. + * @param serverchallenge challenge as sent by the server in the type2 message. * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf(). * @param infotarget infotarget as sent by the server in the type2 message. * @param ntlmv2 calculated session key @@ -1261,27 +1573,25 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len, const char *username, const char *target, time_t now, - const unsigned char serverchallange[8], + const unsigned char serverchallenge[8], const struct ntlm_buf *answer, struct ntlm_buf *infotarget, unsigned char ntlmv2[16]) { krb5_error_code ret; - unsigned int hmaclen; unsigned char clientanswer[16]; unsigned char clientnonce[8]; unsigned char serveranswer[16]; krb5_storage *sp; - HMAC_CTX c; - uint64_t t; time_t authtime; uint32_t temp; + uint64_t t; infotarget->length = 0; infotarget->data = NULL; if (answer->length < 16) - return EINVAL; + return HNTLM_ERR_INVALID_LENGTH; if (now == 0) now = time(NULL); @@ -1312,11 +1622,11 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len, authtime = nt2unixtime(t); if (abs((int)(authtime - now)) > authtimediff) { - ret = EINVAL; + ret = HNTLM_ERR_TIME_SKEW; goto out; } - /* client challange */ + /* client challenge */ CHECK(krb5_storage_read(sp, clientnonce, 8), 8); CHECK(krb5_ret_uint32(sp, &temp), 0); /* unknown */ @@ -1334,16 +1644,19 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len, krb5_storage_free(sp); sp = NULL; - HMAC_CTX_init(&c); - HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL); - HMAC_Update(&c, serverchallange, 8); - HMAC_Update(&c, ((unsigned char *)answer->data) + 16, answer->length - 16); - HMAC_Final(&c, serveranswer, &hmaclen); - HMAC_CTX_cleanup(&c); + if (answer->length < 16) { + ret = HNTLM_ERR_INVALID_LENGTH; + goto out; + } + + heim_ntlm_derive_ntlm2_sess(ntlmv2, + ((unsigned char *)answer->data) + 16, answer->length - 16, + serverchallenge, + serveranswer); if (memcmp(serveranswer, clientanswer, 16) != 0) { heim_ntlm_free_buf(infotarget); - return EINVAL; + return HNTLM_ERR_AUTH; } return 0; @@ -1377,24 +1690,24 @@ heim_ntlm_calculate_ntlm2_sess(const unsigned char clnt_nonce[8], struct ntlm_buf *lm, struct ntlm_buf *ntlm) { - unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH]; + unsigned char ntlm2_sess_hash[8]; unsigned char res[21], *resp; - EVP_MD_CTX *m; + int code; - m = EVP_MD_CTX_create(); - if (m == NULL) - return ENOMEM; + code = heim_ntlm_calculate_ntlm2_sess_hash(clnt_nonce, svr_chal, + ntlm2_sess_hash); + if (code) { + return code; + } lm->data = malloc(24); if (lm->data == NULL) { - EVP_MD_CTX_destroy(m); return ENOMEM; } lm->length = 24; ntlm->data = malloc(24); if (ntlm->data == NULL) { - EVP_MD_CTX_destroy(m); free(lm->data); lm->data = NULL; return ENOMEM; @@ -1405,12 +1718,6 @@ heim_ntlm_calculate_ntlm2_sess(const unsigned char clnt_nonce[8], memset(lm->data, 0, 24); memcpy(lm->data, clnt_nonce, 8); - EVP_DigestInit_ex(m, EVP_md5(), NULL); - EVP_DigestUpdate(m, svr_chal, 8); /* session nonce part 1 */ - EVP_DigestUpdate(m, clnt_nonce, 8); /* session nonce part 2 */ - EVP_DigestFinal_ex(m, ntlm2_sess_hash, NULL); /* will only use first 8 bytes */ - EVP_MD_CTX_destroy(m); - memset(res, 0, sizeof(res)); memcpy(res, ntlm_hash, 16); @@ -1421,3 +1728,73 @@ heim_ntlm_calculate_ntlm2_sess(const unsigned char clnt_nonce[8], return 0; } + + +/* + * Calculate the NTLM2 Session "Verifier" + * + * @param clnt_nonce client nonce + * @param svr_chal server challage + * @param hash The NTLM session verifier + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core + */ + +int +heim_ntlm_calculate_ntlm2_sess_hash(const unsigned char clnt_nonce[8], + const unsigned char svr_chal[8], + unsigned char verifier[8]) +{ + unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH]; + EVP_MD_CTX *m; + + m = EVP_MD_CTX_create(); + if (m == NULL) + return ENOMEM; + + EVP_DigestInit_ex(m, EVP_md5(), NULL); + EVP_DigestUpdate(m, svr_chal, 8); /* session nonce part 1 */ + EVP_DigestUpdate(m, clnt_nonce, 8); /* session nonce part 2 */ + EVP_DigestFinal_ex(m, ntlm2_sess_hash, NULL); /* will only use first 8 bytes */ + EVP_MD_CTX_destroy(m); + + memcpy(verifier, ntlm2_sess_hash, 8); + + return 0; +} + + +/* + * Derive a NTLM2 session key + * + * @param sessionkey session key from domain controller + * @param clnt_nonce client nonce + * @param svr_chal server challenge + * @param derivedkey salted session key + * + * @return In case of success 0 is return, an errors, a errno in what + * went wrong. + * + * @ingroup ntlm_core + */ + +void +heim_ntlm_derive_ntlm2_sess(const unsigned char sessionkey[16], + const unsigned char *clnt_nonce, size_t clnt_nonce_length, + const unsigned char svr_chal[8], + unsigned char derivedkey[16]) +{ + unsigned int hmaclen; + HMAC_CTX c; + + /* HMAC(Ksession, serverchallenge || clientchallenge) */ + HMAC_CTX_init(&c); + HMAC_Init_ex(&c, sessionkey, 16, EVP_md5(), NULL); + HMAC_Update(&c, svr_chal, 8); + HMAC_Update(&c, clnt_nonce, clnt_nonce_length); + HMAC_Final(&c, derivedkey, &hmaclen); + HMAC_CTX_cleanup(&c); +} -- cgit