summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2010-11-11 11:27:33 +1100
committerAndrew Bartlett <abartlet@samba.org>2010-11-15 01:25:06 +0000
commit1342185e333cb8139b7a70b7fe43571bcc2716a7 (patch)
tree0e1cb8d3cfc437bd7cc3a97f2bdc472f54d95dbd
parent13fd22f61017124d2d4964db3e32c667d119b56c (diff)
downloadsamba-1342185e333cb8139b7a70b7fe43571bcc2716a7.tar.gz
samba-1342185e333cb8139b7a70b7fe43571bcc2716a7.tar.bz2
samba-1342185e333cb8139b7a70b7fe43571bcc2716a7.zip
s4:heimdal: import lorikeet-heimdal-201011102149 (commit 5734d03c20e104c8f45533d07f2a2cbbd3224f29)
-rw-r--r--source4/heimdal/kdc/default_config.c44
-rw-r--r--source4/heimdal/kuser/kinit.c5
-rw-r--r--source4/heimdal/lib/asn1/asn1parse.c3042
-rw-r--r--source4/heimdal/lib/asn1/asn1parse.h255
-rw-r--r--source4/heimdal/lib/asn1/asn1parse.y28
-rw-r--r--source4/heimdal/lib/asn1/gen_decode.c8
-rw-r--r--source4/heimdal/lib/asn1/lex.h2
-rw-r--r--source4/heimdal/lib/asn1/lex.l10
-rw-r--r--source4/heimdal/lib/asn1/symbol.c2
-rw-r--r--source4/heimdal/lib/com_err/lex.h2
-rw-r--r--source4/heimdal/lib/com_err/lex.l4
-rw-r--r--source4/heimdal/lib/com_err/parse.y2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/init_sec_context.c27
-rw-r--r--source4/heimdal/lib/hcrypto/dh-imath.c254
-rw-r--r--source4/heimdal/lib/hcrypto/dh-ltm.c41
-rw-r--r--source4/heimdal/lib/hcrypto/dh.c8
-rw-r--r--source4/heimdal/lib/hcrypto/dh.h2
-rw-r--r--source4/heimdal/lib/hcrypto/engine.c20
-rw-r--r--source4/heimdal/lib/hcrypto/imath/LICENSE21
-rw-r--r--source4/heimdal/lib/hcrypto/imath/imath.c3353
-rw-r--r--source4/heimdal/lib/hcrypto/imath/imath.h231
-rw-r--r--source4/heimdal/lib/hcrypto/imath/iprime.c189
-rw-r--r--source4/heimdal/lib/hcrypto/imath/iprime.h51
-rw-r--r--source4/heimdal/lib/hcrypto/rsa-imath.c688
-rw-r--r--source4/heimdal/lib/hcrypto/rsa.c17
-rw-r--r--source4/heimdal/lib/hcrypto/rsa.h2
-rw-r--r--source4/heimdal/lib/hcrypto/sha.h6
-rw-r--r--source4/heimdal/lib/hcrypto/sha512.c108
-rw-r--r--source4/heimdal/lib/hx509/cms.c14
-rw-r--r--source4/heimdal/lib/hx509/collector.c1
-rw-r--r--source4/heimdal/lib/hx509/crypto.c103
-rw-r--r--source4/heimdal/lib/hx509/hx509.h8
-rw-r--r--source4/heimdal/lib/hx509/hx509_err.et1
-rw-r--r--source4/heimdal/lib/hx509/ks_file.c3
-rw-r--r--source4/heimdal/lib/hx509/ks_p12.c1
-rw-r--r--source4/heimdal/lib/krb5/context.c26
-rw-r--r--source4/heimdal/lib/krb5/crypto.c2720
-rw-r--r--source4/heimdal/lib/krb5/data.c19
-rw-r--r--source4/heimdal/lib/krb5/get_cred.c96
-rw-r--r--source4/heimdal/lib/krb5/krb5_locl.h5
-rw-r--r--source4/heimdal/lib/krb5/misc.c7
-rw-r--r--source4/heimdal/lib/krb5/mit_glue.c3
-rw-r--r--source4/heimdal/lib/krb5/pac.c157
-rw-r--r--source4/heimdal/lib/krb5/plugin.c257
-rw-r--r--source4/heimdal/lib/krb5/store.c24
-rw-r--r--source4/heimdal/lib/ntlm/heimntlm.h21
-rw-r--r--source4/heimdal/lib/ntlm/ntlm.c707
47 files changed, 1373 insertions, 11222 deletions
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 <http://www.gnu.org/licenses/>. */
-
-/* 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 <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#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 <stddef.h> /* 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 <libintl.h> /* 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 <alloca.h> /* INFRINGES ON USER NAME SPACE */
-# elif defined _AIX
-# define YYSTACK_ALLOC __alloca
-# elif defined _MSC_VER
-# include <malloc.h> /* 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 <stdlib.h> /* 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 <stdlib.h> /* 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 <stdio.h> /* 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 <http://www.gnu.org/licenses/>. */
-
-/* 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 <roken.h>
-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 <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <dh.h>
-
-#ifdef USE_HCRYPTO_IMATH
-
-#include <roken.h>
-
-#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 <http://spinning-yarns.org/michael/>
- 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 <stdio.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include <assert.h>
-
-#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_<v_){T xch=*u_;*u_++=*v_;*v_--=xch;}}while(0)
-
-#define CLAMP(Z) \
-do{mp_int z_=(Z);mp_size uz_=MP_USED(z_);mp_digit *dz_=MP_DIGITS(z_)+uz_-1;\
-while(uz_ > 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 <half@halssoftware.com>
- 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 <http://spinning-yarns.org/michael/>
- 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 <limits.h>
-
-#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 <http://spinning-yarns.org/michael/>
- 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 <stdlib.h>
-
-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 <http://spinning-yarns.org/michael/>
- 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 <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <krb5-types.h>
-#include <assert.h>
-
-#include <rsa.h>
-
-#include <roken.h>
-
-#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 <pkinit_asn1.h>
#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'
- */
-
-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);
-}
-
-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) {
@@ -1179,197 +149,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,
const void *data,
@@ -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,181 +266,14 @@ 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 = {
+struct checksum_type _krb5_checksum_sha1 = {
CKSUMTYPE_SHA1,
"sha1",
64,
@@ -1670,74 +282,14 @@ static struct checksum_type checksum_sha1 = {
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",
- 64,
- 16,
- F_KEYED | F_CPROOF,
- HMAC_MD5_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);
@@ -2012,7 +562,7 @@ krb5_checksumsize(krb5_context context,
krb5_cksumtype type,
size_t *size)
{
- struct checksum_type *ct = _find_checksum(type);
+ 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", ""),
@@ -2027,7 +577,7 @@ 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);
+ struct checksum_type *ct = _krb5_find_checksum(type);
if(ct == NULL) {
if (context)
krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
@@ -2042,7 +592,7 @@ 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);
+ struct checksum_type *ct = _krb5_find_checksum(type);
if(ct == NULL) {
if (context)
krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
@@ -2057,7 +607,7 @@ 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);
+ struct checksum_type *ct = _krb5_find_checksum(type);
if(ct == NULL) {
if (context)
krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
@@ -2073,709 +623,13 @@ krb5_checksum_disable(krb5_context context,
* *
************************************************************/
-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;
- }
-
- ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
- if (ret) {
- krb5_data_free(&result.checksum);
- return ret;
- }
-
- if (result.checksum.length < crypto->et->blocksize)
- krb5_abortx(context, "internal prf error");
-
- derived = NULL;
- ret = krb5_derive_key(context, crypto->key.key,
- crypto->et->type, "prf", 3, &derived);
- if (ret)
- krb5_abortx(context, "krb5_derive_key");
-
- 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_data_free(&result.checksum);
- krb5_free_keyblock(context, derived);
-
- return ret;
-}
-
-/*
- * 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
-};
-
-static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[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 <assert.h>
+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 <com_err.h>
+#include <heimbase.h>
+
#define HEIMDAL_TEXTDOMAIN "heimdal_krb5"
#ifdef LIBINTL
@@ -176,6 +178,9 @@ struct _krb5_krb_auth_data;
#ifdef PKINIT
#include <hx509.h>
#endif
+
+#include "crypto.h"
+
#include <krb5-private.h>
#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
@@ -76,6 +76,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 <ntlm_err.h>
#include <heimntlm-protos.h>
#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 <limits.h>
#include <roken.h>
+#include <parse_units.h>
#include <krb5.h>
#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.
*
@@ -1001,68 +1239,101 @@ 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);
+}