s4:heimdal: import lorikeet-heimdal-201011102149 (commit 5734d03c20e104c8f45533d07f2a...
authorAndrew Bartlett <abartlet@samba.org>
Thu, 11 Nov 2010 00:27:33 +0000 (11:27 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 15 Nov 2010 01:25:06 +0000 (01:25 +0000)
47 files changed:
source4/heimdal/kdc/default_config.c
source4/heimdal/kuser/kinit.c
source4/heimdal/lib/asn1/asn1parse.c [deleted file]
source4/heimdal/lib/asn1/asn1parse.h [deleted file]
source4/heimdal/lib/asn1/asn1parse.y
source4/heimdal/lib/asn1/gen_decode.c
source4/heimdal/lib/asn1/lex.h
source4/heimdal/lib/asn1/lex.l
source4/heimdal/lib/asn1/symbol.c
source4/heimdal/lib/com_err/lex.h
source4/heimdal/lib/com_err/lex.l
source4/heimdal/lib/com_err/parse.y
source4/heimdal/lib/gssapi/krb5/init_sec_context.c
source4/heimdal/lib/hcrypto/dh-imath.c [deleted file]
source4/heimdal/lib/hcrypto/dh-ltm.c
source4/heimdal/lib/hcrypto/dh.c
source4/heimdal/lib/hcrypto/dh.h
source4/heimdal/lib/hcrypto/engine.c
source4/heimdal/lib/hcrypto/imath/LICENSE [deleted file]
source4/heimdal/lib/hcrypto/imath/imath.c [deleted file]
source4/heimdal/lib/hcrypto/imath/imath.h [deleted file]
source4/heimdal/lib/hcrypto/imath/iprime.c [deleted file]
source4/heimdal/lib/hcrypto/imath/iprime.h [deleted file]
source4/heimdal/lib/hcrypto/rsa-imath.c [deleted file]
source4/heimdal/lib/hcrypto/rsa.c
source4/heimdal/lib/hcrypto/rsa.h
source4/heimdal/lib/hcrypto/sha.h
source4/heimdal/lib/hcrypto/sha512.c
source4/heimdal/lib/hx509/cms.c
source4/heimdal/lib/hx509/collector.c
source4/heimdal/lib/hx509/crypto.c
source4/heimdal/lib/hx509/hx509.h
source4/heimdal/lib/hx509/hx509_err.et
source4/heimdal/lib/hx509/ks_file.c
source4/heimdal/lib/hx509/ks_p12.c
source4/heimdal/lib/krb5/context.c
source4/heimdal/lib/krb5/crypto.c
source4/heimdal/lib/krb5/data.c
source4/heimdal/lib/krb5/get_cred.c
source4/heimdal/lib/krb5/krb5_locl.h
source4/heimdal/lib/krb5/misc.c
source4/heimdal/lib/krb5/mit_glue.c
source4/heimdal/lib/krb5/pac.c
source4/heimdal/lib/krb5/plugin.c
source4/heimdal/lib/krb5/store.c
source4/heimdal/lib/ntlm/heimntlm.h
source4/heimdal/lib/ntlm/ntlm.c

index 118bdf97aa62723b56d626e69ca76e8a58d7c666..f745183e5147baa433d3250bbeddca620432ba98 100644 (file)
@@ -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 */
 }
index e6201fbbc03894ac3f6a8168e7b31790d69f5a4e..11e364980dc5e5a6cf73e058195735c722474fe9 100644 (file)
@@ -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 (file)
index 4c2ae26..0000000
+++ /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
-
-\f
-
-#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 */
-\f
-
-/*-----------------------------------------------.
-| 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 (file)
index dc3debb..0000000
+++ /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;
-
-
index 9ff9ad770721de380d699d4f344360b180bc653c..dad7f67a20229e870752ed9c6163913b2f92c655 100644 (file)
@@ -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 *
index 5a24339c4274c949ff43200d8329ca52d708e958..002a471e96e7dc33c8e012e0cf1b144625eb6883 100644 (file)
@@ -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);
index f203c98f1fa030559d0883409f1e2f57823e983c..1ee534178996b855847608866d3823455b176d4e 100644 (file)
@@ -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;
 
index 3507d64b3ad93ccdf5b84a535550eb64161c9c77..dece0961646cc79e83e0dd03f6c9d7daca11c37c 100644 (file)
@@ -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);
 }
index 93d2cd4594c9ebc27b60f1ebda034c019b90f057..b05f68fa74a9f9b9ac3b386115c6326ed195babd 100644 (file)
@@ -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;
index abfec922f04a0f848ef567a97cf8b75577fa889d..76f3e2b2a5db60ee4398f39db13dc3959e0ac511 100644 (file)
@@ -33,7 +33,7 @@
 
 /* $Id$ */
 
-void lex_err_message (const char *, ...)
+void error_message (const char *, ...)
 __attribute__ ((format (printf, 1, 2)));
 
 int yylex(void);
index f099c1e1bd3cc24270d5a5f8a2a80eb51e057fc6..b68814b21caa0993ae4b45acc31efb7118091543 100644 (file)
@@ -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;
 
index f1ae64d97e806c0eb7dee3f78fa05fb1bcbb832d..d64681d90234dc0434426f2508a92e5ee15ddee0 100644 (file)
@@ -167,5 +167,5 @@ name2number(const char *str)
 void
 yyerror (char *s)
 {
-     lex_err_message ("%s\n", s);
+     error_message ("%s\n", s);
 }
index 4538a5376e59b6a7c2912291a2896bcb8af276fd..53855ca045322993ac766573ae6e39ca3401800d 100644 (file)
@@ -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 (file)
index c2e86fa..0000000
+++ /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
-}
index 6166100b082d915600e0b1bf9ee155755a81c693..f66cd5aff2e2a5e62a6c3448696c8588fe0a252d 100644 (file)
@@ -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
  */
index 3ad37f87a78c7ded677b28b522817909959edaa0..43e1d6ac1b886ab4d643ee0618bf1537f77cf12a 100644 (file)
@@ -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.
index 3a24f9dfdfcbb9ad6e5825006e06a76272328c18..637f218bcf8222cae503a97d16398d9d2c94b02e 100644 (file)
@@ -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 *);
index 6e3e5e3939632b8ef02c34fd3ce75eea8f81ee7f..15853420f6de5d7501533c683993c771e8ba3ffb 100644 (file)
@@ -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 (file)
index 5b0104f..0000000
+++ /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 (file)
index 0079baf..0000000
+++ /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 (file)
index cb87795..0000000
+++ /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 (file)
index 2bc9e7a..0000000
+++ /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 (file)
index 6110dcc..0000000
+++ /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 (file)
index 23d5352..0000000
+++ /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
-}
index a6e09fe2834bb0ddcc38e499dfe146682a687233..235686999e59938ceb9b1d5a270a1a0a64f5a015 100644 (file)
  * 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;
index 3fd805fcf07fb7afe3b388831310ec2f586bfc66..798852d3f1587e98b00930f37f71f1837c929221 100644 (file)
@@ -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);
index a1f5a993189ce98ae69af077695dfe8b96dcdf50..fbc1810b4aee875b55984b0d417d3695f7a1eacc 100644 (file)
 #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
index 18447b6c67ad7e45fa3e7bc43efba7c8956a2b99..fb38cadb6f0a2ef439a9f413c1d9efa22d95f084 100644 (file)
@@ -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.
  *
 #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
index 224c39086c4e064360d525c594a5b98844988116..ef986fd4edf1a3ef627d05d6275e4cb9abcaf377 100644 (file)
@@ -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 "
index ab36fe2dc8f05ddf55413941c3c8372e5e92a5a9..1a44de00a34621a623369385b8674456ffafb581 100644 (file)
@@ -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;
index de7717af0297debc1ed350136004389c1f1c8c15..a38226d94cb089d0ede0aea10e36b60264491828 100644 (file)
@@ -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);
 }
 
 /*
index b6eeac9d18a2f33de8ea3417ef4e54f3bafd76d7..1a5e2f30807e4ae573e6222aa7ffd41d37be4546 100644 (file)
@@ -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
index 76bbfaeabaa1a8fdb482f08282d5668a567562b8..6225f125fb2011a92d1c90bafc30cde92ec65aeb 100644 (file)
@@ -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
index 645dc405a2b4501d904ee4d5f78e8767ba2994f8..ecd3a6edaaa96a3691299d608e00455f6c92ea15 100644 (file)
@@ -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,
index d94ab197cd6ca8be79e06ef3258e0da6f2d45822..704cf071d7d04e9854013290477d1cc3a45505af 100644 (file)
@@ -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);
index f68ab46cec9cf3c84aa147b904a3eb4ee730debc..100eb1237d889dcd096da2f789bc040a0b7e6ece 100644 (file)
@@ -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;
index d5d9c1d9d552b864f2f61a1e15e5d0e5220489ed..f0b0692bc04b01773ac9341755b49b88d1b159d1 100644 (file)
 #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'
- */
+static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
+                                       unsigned, struct key_data**);
+static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
 
-KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
-krb5_string_to_key_salt (krb5_context context,
-                        krb5_enctype enctype,
-                        const char *password,
-                        krb5_salt salt,
-                        krb5_keyblock *key)
-{
-    krb5_data pw;
-    pw.data = rk_UNCONST(password);
-    pw.length = strlen(password);
-    return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
-}
+static void free_key_schedule(krb5_context,
+                             struct key_data *,
+                             struct encryption_type *);
 
-KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
-krb5_string_to_key_salt_opaque (krb5_context context,
-                               krb5_enctype enctype,
-                               const char *password,
-                               krb5_salt salt,
-                               krb5_data opaque,
-                               krb5_keyblock *key)
-{
-    krb5_data pw;
-    pw.data = rk_UNCONST(password);
-    pw.length = strlen(password);
-    return krb5_string_to_key_data_salt_opaque(context, enctype,
-                                              pw, salt, opaque, key);
-}
+/************************************************************
+ *                                                          *
+ ************************************************************/
 
 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enctype_keysize(krb5_context context,
                     krb5_enctype type,
                     size_t *keysize)
 {
-    struct encryption_type *et = _find_enctype(type);
+    struct encryption_type *et = _krb5_find_enctype(type);
     if(et == NULL) {
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
                               N_("encryption type %d not supported", ""),
@@ -1102,7 +72,7 @@ krb5_enctype_keybits(krb5_context context,
                     krb5_enctype type,
                     size_t *keybits)
 {
-    struct encryption_type *et = _find_enctype(type);
+    struct encryption_type *et = _krb5_find_enctype(type);
     if(et == NULL) {
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
                               "encryption type %d not supported",
@@ -1119,7 +89,7 @@ krb5_generate_random_keyblock(krb5_context context,
                              krb5_keyblock *key)
 {
     krb5_error_code ret;
-    struct encryption_type *et = _find_enctype(type);
+    struct encryption_type *et = _krb5_find_enctype(type);
     if(et == NULL) {
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
                               N_("encryption type %d not supported", ""),
@@ -1143,7 +113,7 @@ _key_schedule(krb5_context context,
              struct key_data *key)
 {
     krb5_error_code ret;
-    struct encryption_type *et = _find_enctype(key->key->keytype);
+    struct encryption_type *et = _krb5_find_enctype(key->key->keytype);
     struct key_type *kt;
 
     if (et == NULL) {
@@ -1178,197 +148,6 @@ _key_schedule(krb5_context context,
  *                                                          *
  ************************************************************/
 
-static krb5_error_code
-NONE_checksum(krb5_context context,
-             struct key_data *key,
-             const void *data,
-             size_t len,
-             unsigned usage,
-             Checksum *C)
-{
-    return 0;
-}
-
-#if defined(DES3_OLD_ENCTYPE) || defined(HEIM_WEAK_CRYPTO)
-
-static krb5_error_code
-des_checksum(krb5_context context,
-            const EVP_MD *evp_md,
-            struct key_data *key,
-            const void *data,
-            size_t len,
-            Checksum *cksum)
-{
-    struct evp_schedule *ctx = key->schedule->data;
-    EVP_MD_CTX *m;
-    DES_cblock ivec;
-    unsigned char *p = cksum->checksum.data;
-
-    krb5_generate_random_block(p, 8);
-
-    m = EVP_MD_CTX_create();
-    if (m == NULL) {
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
-
-    EVP_DigestInit_ex(m, evp_md, NULL);
-    EVP_DigestUpdate(m, p, 8);
-    EVP_DigestUpdate(m, data, len);
-    EVP_DigestFinal_ex (m, p + 8, NULL);
-    EVP_MD_CTX_destroy(m);
-    memset (&ivec, 0, sizeof(ivec));
-    EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1);
-    EVP_Cipher(&ctx->ectx, p, p, 24);
-
-    return 0;
-}
-
-static krb5_error_code
-des_verify(krb5_context context,
-          const EVP_MD *evp_md,
-          struct key_data *key,
-          const void *data,
-          size_t len,
-          Checksum *C)
-{
-    struct evp_schedule *ctx = key->schedule->data;
-    EVP_MD_CTX *m;
-    unsigned char tmp[24];
-    unsigned char res[16];
-    DES_cblock ivec;
-    krb5_error_code ret = 0;
-
-    m = EVP_MD_CTX_create();
-    if (m == NULL) {
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
-
-    memset(&ivec, 0, sizeof(ivec));
-    EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1);
-    EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24);
-
-    EVP_DigestInit_ex(m, evp_md, NULL);
-    EVP_DigestUpdate(m, tmp, 8); /* confounder */
-    EVP_DigestUpdate(m, data, len);
-    EVP_DigestFinal_ex (m, res, NULL);
-    EVP_MD_CTX_destroy(m);
-    if(ct_memcmp(res, tmp + 8, sizeof(res)) != 0) {
-       krb5_clear_error_message (context);
-       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-    }
-    memset(tmp, 0, sizeof(tmp));
-    memset(res, 0, sizeof(res));
-    return ret;
-}
-
-#endif
-
-#ifdef HEIM_WEAK_CRYPTO
-
-static krb5_error_code
-CRC32_checksum(krb5_context context,
-              struct key_data *key,
-              const void *data,
-              size_t len,
-              unsigned usage,
-              Checksum *C)
-{
-    uint32_t crc;
-    unsigned char *r = C->checksum.data;
-    _krb5_crc_init_table ();
-    crc = _krb5_crc_update (data, len, 0);
-    r[0] = crc & 0xff;
-    r[1] = (crc >> 8)  & 0xff;
-    r[2] = (crc >> 16) & 0xff;
-    r[3] = (crc >> 24) & 0xff;
-    return 0;
-}
-
-static krb5_error_code
-RSA_MD4_checksum(krb5_context context,
-                struct key_data *key,
-                const void *data,
-                size_t len,
-                unsigned usage,
-                Checksum *C)
-{
-    if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1)
-       krb5_abortx(context, "md4 checksum failed");
-    return 0;
-}
-
-static krb5_error_code
-RSA_MD4_DES_checksum(krb5_context context,
-                    struct key_data *key,
-                    const void *data,
-                    size_t len,
-                    unsigned usage,
-                    Checksum *cksum)
-{
-    return des_checksum(context, EVP_md4(), key, data, len, cksum);
-}
-
-static krb5_error_code
-RSA_MD4_DES_verify(krb5_context context,
-                  struct key_data *key,
-                  const void *data,
-                  size_t len,
-                  unsigned usage,
-                  Checksum *C)
-{
-    return des_verify(context, EVP_md5(), key, data, len, C);
-}
-
-static krb5_error_code
-RSA_MD5_DES_checksum(krb5_context context,
-                    struct key_data *key,
-                    const void *data,
-                    size_t len,
-                    unsigned usage,
-                    Checksum *C)
-{
-    return des_checksum(context, EVP_md5(), key, data, len, C);
-}
-
-static krb5_error_code
-RSA_MD5_DES_verify(krb5_context context,
-                  struct key_data *key,
-                  const void *data,
-                  size_t len,
-                  unsigned usage,
-                  Checksum *C)
-{
-    return des_verify(context, EVP_md5(), key, data, len, C);
-}
-
-#endif /* HEIM_WEAK_CRYPTO */
-
-#ifdef DES3_OLD_ENCTYPE
-static krb5_error_code
-RSA_MD5_DES3_checksum(krb5_context context,
-                     struct key_data *key,
-                     const void *data,
-                     size_t len,
-                     unsigned usage,
-                     Checksum *C)
-{
-    return des_checksum(context, EVP_md5(), key, data, len, C);
-}
-
-static krb5_error_code
-RSA_MD5_DES3_verify(krb5_context context,
-                   struct key_data *key,
-                   const void *data,
-                   size_t len,
-                   unsigned usage,
-                   Checksum *C)
-{
-    return des_verify(context, EVP_md5(), key, data, len, C);
-}
-#endif
-
 static krb5_error_code
 SHA1_checksum(krb5_context context,
              struct key_data *key,
@@ -1383,14 +162,14 @@ SHA1_checksum(krb5_context context,
 }
 
 /* HMAC according to RFC2104 */
-static krb5_error_code
-hmac(krb5_context context,
-     struct checksum_type *cm,
-     const void *data,
-     size_t len,
-     unsigned usage,
-     struct key_data *keyblock,
-     Checksum *result)
+krb5_error_code
+_krb5_internal_hmac(krb5_context context,
+                   struct checksum_type *cm,
+                   const void *data,
+                   size_t len,
+                   unsigned usage,
+                   struct key_data *keyblock,
+                   Checksum *result)
 {
     unsigned char *ipad, *opad;
     unsigned char *key;
@@ -1449,7 +228,7 @@ krb5_hmac(krb5_context context,
          krb5_keyblock *key,
          Checksum *result)
 {
-    struct checksum_type *c = _find_checksum(cktype);
+    struct checksum_type *c = _krb5_find_checksum(cktype);
     struct key_data kd;
     krb5_error_code ret;
 
@@ -1463,7 +242,7 @@ krb5_hmac(krb5_context context,
     kd.key = key;
     kd.schedule = NULL;
 
-    ret = hmac(context, c, data, len, usage, &kd, result);
+    ret = _krb5_internal_hmac(context, c, data, len, usage, &kd, result);
 
     if (kd.schedule)
        krb5_free_data(context, kd.schedule);
@@ -1471,15 +250,15 @@ krb5_hmac(krb5_context context,
     return ret;
 }
 
-static krb5_error_code
-SP_HMAC_SHA1_checksum(krb5_context context,
-                     struct key_data *key,
-                     const void *data,
-                     size_t len,
-                     unsigned usage,
-                     Checksum *result)
+krb5_error_code
+_krb5_SP_HMAC_SHA1_checksum(krb5_context context,
+                           struct key_data *key,
+                           const void *data,
+                           size_t len,
+                           unsigned usage,
+                           Checksum *result)
 {
-    struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
+    struct checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1);
     Checksum res;
     char sha1_data[20];
     krb5_error_code ret;
@@ -1487,257 +266,30 @@ SP_HMAC_SHA1_checksum(krb5_context context,
     res.checksum.data = sha1_data;
     res.checksum.length = sizeof(sha1_data);
 
-    ret = hmac(context, c, data, len, usage, key, &res);
+    ret = _krb5_internal_hmac(context, c, data, len, usage, key, &res);
     if (ret)
        krb5_abortx(context, "hmac failed");
     memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
     return 0;
-}
-
-/*
- * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
- *
- * This function made available to PAC routines
- */
-
-static krb5_error_code
-HMAC_MD5_checksum(krb5_context context,
-                 struct key_data *key,
-                 const void *data,
-                 size_t len,
-                 unsigned usage,
-                 Checksum *result)
-{
-    EVP_MD_CTX *m;
-    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
-    const char signature[] = "signaturekey";
-    Checksum ksign_c;
-    struct key_data ksign;
-    krb5_keyblock kb;
-    unsigned char t[4];
-    unsigned char tmp[16];
-    unsigned char ksign_c_data[16];
-    krb5_error_code ret;
-
-    m = EVP_MD_CTX_create();
-    if (m == NULL) {
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
-    ksign_c.checksum.length = sizeof(ksign_c_data);
-    ksign_c.checksum.data   = ksign_c_data;
-    ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
-    if (ret) {
-       EVP_MD_CTX_destroy(m);
-       return ret;
-    }
-    ksign.key = &kb;
-    kb.keyvalue = ksign_c.checksum;
-    EVP_DigestInit_ex(m, EVP_md5(), NULL);
-    t[0] = (usage >>  0) & 0xFF;
-    t[1] = (usage >>  8) & 0xFF;
-    t[2] = (usage >> 16) & 0xFF;
-    t[3] = (usage >> 24) & 0xFF;
-    EVP_DigestUpdate(m, t, 4);
-    EVP_DigestUpdate(m, data, len);
-    EVP_DigestFinal_ex (m, tmp, NULL);
-    EVP_MD_CTX_destroy(m);
-
-    ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
-    if (ret)
-       return ret;
-    return 0;
-}
-
-/* HMAC-MD5 checksum over any key (needed for the PAC routines) */
-krb5_error_code
-HMAC_MD5_any_checksum(krb5_context context,
-                     const krb5_keyblock *key,
-                     const void *data,
-                     size_t len,
-                     unsigned usage,
-                     Checksum *result)
-{
-       krb5_error_code ret;
-       struct key_data local_key;
-       ret = krb5_copy_keyblock(context, key, &local_key.key);
-       if (ret)
-           return ret;
-
-       local_key.schedule = NULL;
-       ret = krb5_data_alloc (&result->checksum, 16);
-       if (ret)
-           return ret;
-
-       result->cksumtype = CKSUMTYPE_HMAC_MD5;
-       ret = HMAC_MD5_checksum(context, &local_key, data, len, usage, result);
-
-       if (ret)
-               krb5_data_free(&result->checksum);
-
-       krb5_free_keyblock(context, local_key.key);
-       return ret;
-}
-
-static struct checksum_type checksum_none = {
-    CKSUMTYPE_NONE,
-    "none",
-    1,
-    0,
-    0,
-    NONE_checksum,
-    NULL
-};
-#ifdef HEIM_WEAK_CRYPTO
-static struct checksum_type checksum_crc32 = {
-    CKSUMTYPE_CRC32,
-    "crc32",
-    1,
-    4,
-    0,
-    CRC32_checksum,
-    NULL
-};
-static struct checksum_type checksum_rsa_md4 = {
-    CKSUMTYPE_RSA_MD4,
-    "rsa-md4",
-    64,
-    16,
-    F_CPROOF,
-    RSA_MD4_checksum,
-    NULL
-};
-static struct checksum_type checksum_rsa_md4_des = {
-    CKSUMTYPE_RSA_MD4_DES,
-    "rsa-md4-des",
-    64,
-    24,
-    F_KEYED | F_CPROOF | F_VARIANT,
-    RSA_MD4_DES_checksum,
-    RSA_MD4_DES_verify
-};
-static struct checksum_type checksum_rsa_md5_des = {
-    CKSUMTYPE_RSA_MD5_DES,
-    "rsa-md5-des",
-    64,
-    24,
-    F_KEYED | F_CPROOF | F_VARIANT,
-    RSA_MD5_DES_checksum,
-    RSA_MD5_DES_verify
-};
-#endif /* HEIM_WEAK_CRYPTO */
-
-static krb5_error_code
-RSA_MD5_checksum(krb5_context context,
-                struct key_data *key,
-                const void *data,
-                size_t len,
-                unsigned usage,
-                Checksum *C)
-{
-    if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
-       krb5_abortx(context, "md5 checksum failed");
-    return 0;
-}
-
-static struct checksum_type checksum_rsa_md5 = {
-    CKSUMTYPE_RSA_MD5,
-    "rsa-md5",
-    64,
-    16,
-    F_CPROOF,
-    RSA_MD5_checksum,
-    NULL
-};
-
-#ifdef DES3_OLD_ENCTYPE
-static struct checksum_type checksum_rsa_md5_des3 = {
-    CKSUMTYPE_RSA_MD5_DES3,
-    "rsa-md5-des3",
-    64,
-    24,
-    F_KEYED | F_CPROOF | F_VARIANT,
-    RSA_MD5_DES3_checksum,
-    RSA_MD5_DES3_verify
-};
-#endif
-static struct checksum_type checksum_sha1 = {
-    CKSUMTYPE_SHA1,
-    "sha1",
-    64,
-    20,
-    F_CPROOF,
-    SHA1_checksum,
-    NULL
-};
-static struct checksum_type checksum_hmac_sha1_des3 = {
-    CKSUMTYPE_HMAC_SHA1_DES3,
-    "hmac-sha1-des3",
-    64,
-    20,
-    F_KEYED | F_CPROOF | F_DERIVED,
-    SP_HMAC_SHA1_checksum,
-    NULL
-};
-
-static struct checksum_type checksum_hmac_sha1_aes128 = {
-    CKSUMTYPE_HMAC_SHA1_96_AES_128,
-    "hmac-sha1-96-aes128",
-    64,
-    12,
-    F_KEYED | F_CPROOF | F_DERIVED,
-    SP_HMAC_SHA1_checksum,
-    NULL
-};
-
-static struct checksum_type checksum_hmac_sha1_aes256 = {
-    CKSUMTYPE_HMAC_SHA1_96_AES_256,
-    "hmac-sha1-96-aes256",
-    64,
-    12,
-    F_KEYED | F_CPROOF | F_DERIVED,
-    SP_HMAC_SHA1_checksum,
-    NULL
-};
+}
 
-static struct checksum_type checksum_hmac_md5 = {
-    CKSUMTYPE_HMAC_MD5,
-    "hmac-md5",
+struct checksum_type _krb5_checksum_sha1 = {
+    CKSUMTYPE_SHA1,
+    "sha1",
     64,
-    16,
-    F_KEYED | F_CPROOF,
-    HMAC_MD5_checksum,
+    20,
+    F_CPROOF,
+    SHA1_checksum,
     NULL
 };
 
-static struct checksum_type *checksum_types[] = {
-    &checksum_none,
-#ifdef HEIM_WEAK_CRYPTO
-    &checksum_crc32,
-    &checksum_rsa_md4,
-    &checksum_rsa_md4_des,
-    &checksum_rsa_md5_des,
-#endif
-#ifdef DES3_OLD_ENCTYPE
-    &checksum_rsa_md5_des3,
-#endif
-    &checksum_rsa_md5,
-    &checksum_sha1,
-    &checksum_hmac_sha1_des3,
-    &checksum_hmac_sha1_aes128,
-    &checksum_hmac_sha1_aes256,
-    &checksum_hmac_md5
-};
-
-static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
-
-static struct checksum_type *
-_find_checksum(krb5_cksumtype type)
+struct checksum_type *
+_krb5_find_checksum(krb5_cksumtype type)
 {
     int i;
-    for(i = 0; i < num_checksums; i++)
-       if(checksum_types[i]->type == type)
-           return checksum_types[i];
+    for(i = 0; i < _krb5_num_checksums; i++)
+       if(_krb5_checksum_types[i]->type == type)
+           return _krb5_checksum_types[i];
     return NULL;
 }
 
@@ -1832,7 +384,7 @@ krb5_create_checksum(krb5_context context,
 
     /* type 0 -> pick from crypto */
     if (type) {
-       ct = _find_checksum(type);
+       ct = _krb5_find_checksum(type);
     } else if (crypto) {
        ct = crypto->et->keyed_checksum;
        if (ct == NULL)
@@ -1848,7 +400,7 @@ krb5_create_checksum(krb5_context context,
 
     if (arcfour_checksum_p(ct, crypto)) {
        keyusage = usage;
-       usage2arcfour(context, &keyusage);
+       _krb5_usage2arcfour(context, &keyusage);
     } else
        keyusage = CHECKSUM_USAGE(usage);
 
@@ -1870,7 +422,7 @@ verify_checksum(krb5_context context,
     Checksum c;
     struct checksum_type *ct;
 
-    ct = _find_checksum(cksum->cksumtype);
+    ct = _krb5_find_checksum(cksum->cksumtype);
     if (ct == NULL || (ct->flags & F_DISABLED)) {
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
                                N_("checksum type %d not supported", ""),
@@ -1938,9 +490,7 @@ verify_checksum(krb5_context context,
        return ret;
     }
 
-    if(c.checksum.length != cksum->checksum.length ||
-       ct_memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
-       krb5_clear_error_message (context);
+    if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) {
        ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
        krb5_set_error_message(context, ret,
                               N_("Decrypt integrity check failed for checksum "
@@ -1964,7 +514,7 @@ krb5_verify_checksum(krb5_context context,
     struct checksum_type *ct;
     unsigned keyusage;
 
-    ct = _find_checksum(cksum->cksumtype);
+    ct = _krb5_find_checksum(cksum->cksumtype);
     if(ct == NULL) {
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
                                N_("checksum type %d not supported", ""),
@@ -1974,7 +524,7 @@ krb5_verify_checksum(krb5_context context,
 
     if (arcfour_checksum_p(ct, crypto)) {
        keyusage = usage;
-       usage2arcfour(context, &keyusage);
+       _krb5_usage2arcfour(context, &keyusage);
     } else
        keyusage = CHECKSUM_USAGE(usage);
 
@@ -1992,790 +542,94 @@ krb5_crypto_get_checksum_type(krb5_context context,
     if (crypto != NULL) {
         ct = crypto->et->keyed_checksum;
         if (ct == NULL)
-            ct = crypto->et->checksum;
-    }
-
-    if (ct == NULL) {
-       krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
-                               N_("checksum type not found", ""));
-        return KRB5_PROG_SUMTYPE_NOSUPP;
-    }
-
-    *type = ct->type;
-
-    return 0;
-}
-
-
-KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
-krb5_checksumsize(krb5_context context,
-                 krb5_cksumtype type,
-                 size_t *size)
-{
-    struct checksum_type *ct = _find_checksum(type);
-    if(ct == NULL) {
-       krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
-                               N_("checksum type %d not supported", ""),
-                               type);
-       return KRB5_PROG_SUMTYPE_NOSUPP;
-    }
-    *size = ct->checksumsize;
-    return 0;
-}
-
-KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
-krb5_checksum_is_keyed(krb5_context context,
-                      krb5_cksumtype type)
-{
-    struct checksum_type *ct = _find_checksum(type);
-    if(ct == NULL) {
-       if (context)
-           krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
-                                   N_("checksum type %d not supported", ""),
-                                   type);
-       return KRB5_PROG_SUMTYPE_NOSUPP;
-    }
-    return ct->flags & F_KEYED;
-}
-
-KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
-krb5_checksum_is_collision_proof(krb5_context context,
-                                krb5_cksumtype type)
-{
-    struct checksum_type *ct = _find_checksum(type);
-    if(ct == NULL) {
-       if (context)
-           krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
-                                   N_("checksum type %d not supported", ""),
-                                   type);
-       return KRB5_PROG_SUMTYPE_NOSUPP;
-    }
-    return ct->flags & F_CPROOF;
-}
-
-KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
-krb5_checksum_disable(krb5_context context,
-                     krb5_cksumtype type)
-{
-    struct checksum_type *ct = _find_checksum(type);
-    if(ct == NULL) {
-       if (context)
-           krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
-                                   N_("checksum type %d not supported", ""),
-                                   type);
-       return KRB5_PROG_SUMTYPE_NOSUPP;
-    }
-    ct->flags |= F_DISABLED;
-    return 0;
-}
-
-/************************************************************
- *                                                          *
- ************************************************************/
-
-static krb5_error_code
-NULL_encrypt(krb5_context context,
-            struct key_data *key,
-            void *data,
-            size_t len,
-            krb5_boolean encryptp,
-            int usage,
-            void *ivec)
-{
-    return 0;
-}
-
-static krb5_error_code
-evp_encrypt(krb5_context context,
-           struct key_data *key,
-           void *data,
-           size_t len,
-           krb5_boolean encryptp,
-           int usage,
-           void *ivec)
-{
-    struct evp_schedule *ctx = key->schedule->data;
-    EVP_CIPHER_CTX *c;
-    c = encryptp ? &ctx->ectx : &ctx->dctx;
-    if (ivec == NULL) {
-       /* alloca ? */
-       size_t len2 = EVP_CIPHER_CTX_iv_length(c);
-       void *loiv = malloc(len2);
-       if (loiv == NULL) {
-           krb5_clear_error_message(context);
-           return ENOMEM;
-       }
-       memset(loiv, 0, len2);
-       EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
-       free(loiv);
-    } else
-       EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
-    EVP_Cipher(c, data, data, len);
-    return 0;
-}
-
-static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
-
-static krb5_error_code
-evp_encrypt_cts(krb5_context context,
-               struct key_data *key,
-               void *data,
-               size_t len,
-               krb5_boolean encryptp,
-               int usage,
-               void *ivec)
-{
-    size_t i, blocksize;
-    struct evp_schedule *ctx = key->schedule->data;
-    char tmp[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH];
-    EVP_CIPHER_CTX *c;
-    unsigned char *p;
-
-    c = encryptp ? &ctx->ectx : &ctx->dctx;
-
-    blocksize = EVP_CIPHER_CTX_block_size(c);
-
-    if (len < blocksize) {
-       krb5_set_error_message(context, EINVAL,
-                              "message block too short");
-       return EINVAL;
-    } else if (len == blocksize) {
-       EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
-       EVP_Cipher(c, data, data, len);
-       return 0;
-    }
-
-    if (ivec)
-       EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
-    else
-       EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
-
-    if (encryptp) {
-
-       p = data;
-       i = ((len - 1) / blocksize) * blocksize;
-       EVP_Cipher(c, p, p, i);
-       p += i - blocksize;
-       len -= i;
-       memcpy(ivec2, p, blocksize);
-
-       for (i = 0; i < len; i++)
-           tmp[i] = p[i + blocksize] ^ ivec2[i];
-       for (; i < blocksize; i++)
-           tmp[i] = 0 ^ ivec2[i];
-       
-       EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
-       EVP_Cipher(c, p, tmp, blocksize);
-       
-       memcpy(p + blocksize, ivec2, len);
-       if (ivec)
-           memcpy(ivec, p, blocksize);
-    } else { 
-       char tmp2[EVP_MAX_BLOCK_LENGTH], tmp3[EVP_MAX_BLOCK_LENGTH];
-
-       p = data;
-       if (len > blocksize * 2) {
-           /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
-           i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize);
-           memcpy(ivec2, p + i - blocksize, blocksize);
-           EVP_Cipher(c, p, p, i);
-           p += i;
-           len -= i + blocksize;
-       } else {
-           if (ivec)
-               memcpy(ivec2, ivec, blocksize);
-           else
-               memcpy(ivec2, zero_ivec, blocksize);
-           len -= blocksize;
-       }
-
-       memcpy(tmp, p, blocksize);
-       EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
-       EVP_Cipher(c, tmp2, p, blocksize);
-
-       memcpy(tmp3, p + blocksize, len);
-       memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */
-
-       for (i = 0; i < len; i++)
-           p[i + blocksize] = tmp2[i] ^ tmp3[i];
-
-       EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
-       EVP_Cipher(c, p, tmp3, blocksize);
-
-       for (i = 0; i < blocksize; i++)
-           p[i] ^= ivec2[i];
-       if (ivec)
-           memcpy(ivec, tmp, blocksize);
-    }
-    return 0;
-}
-
-#ifdef HEIM_WEAK_CRYPTO
-static krb5_error_code
-evp_des_encrypt_null_ivec(krb5_context context,
-                         struct key_data *key,
-                         void *data,
-                         size_t len,
-                         krb5_boolean encryptp,
-                         int usage,
-                         void *ignore_ivec)
-{
-    struct evp_schedule *ctx = key->schedule->data;
-    EVP_CIPHER_CTX *c;
-    DES_cblock ivec;
-    memset(&ivec, 0, sizeof(ivec));
-    c = encryptp ? &ctx->ectx : &ctx->dctx;
-    EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
-    EVP_Cipher(c, data, data, len);
-    return 0;
-}
-
-static krb5_error_code
-evp_des_encrypt_key_ivec(krb5_context context,
-                        struct key_data *key,
-                        void *data,
-                        size_t len,
-                        krb5_boolean encryptp,
-                        int usage,
-                        void *ignore_ivec)
-{
-    struct evp_schedule *ctx = key->schedule->data;
-    EVP_CIPHER_CTX *c;
-    DES_cblock ivec;
-    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
-    c = encryptp ? &ctx->ectx : &ctx->dctx;
-    EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
-    EVP_Cipher(c, data, data, len);
-    return 0;
-}
-
-static krb5_error_code
-DES_CFB64_encrypt_null_ivec(krb5_context context,
-                           struct key_data *key,
-                           void *data,
-                           size_t len,
-                           krb5_boolean encryptp,
-                           int usage,
-                           void *ignore_ivec)
-{
-    DES_cblock ivec;
-    int num = 0;
-    DES_key_schedule *s = key->schedule->data;
-    memset(&ivec, 0, sizeof(ivec));
-
-    DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
-    return 0;
-}
-
-static krb5_error_code
-DES_PCBC_encrypt_key_ivec(krb5_context context,
-                         struct key_data *key,
-                         void *data,
-                         size_t len,
-                         krb5_boolean encryptp,
-                         int usage,
-                         void *ignore_ivec)
-{
-    DES_cblock ivec;
-    DES_key_schedule *s = key->schedule->data;
-    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
-
-    DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
-    return 0;
-}
-#endif
-
-/*
- * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
- *
- * warning: not for small children
- */
-
-static krb5_error_code
-ARCFOUR_subencrypt(krb5_context context,
-                  struct key_data *key,
-                  void *data,
-                  size_t len,
-                  unsigned usage,
-                  void *ivec)
-{
-    EVP_CIPHER_CTX ctx;
-    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
-    Checksum k1_c, k2_c, k3_c, cksum;
-    struct key_data ke;
-    krb5_keyblock kb;
-    unsigned char t[4];
-    unsigned char *cdata = data;
-    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
-    krb5_error_code ret;
-
-    t[0] = (usage >>  0) & 0xFF;
-    t[1] = (usage >>  8) & 0xFF;
-    t[2] = (usage >> 16) & 0xFF;
-    t[3] = (usage >> 24) & 0xFF;
-
-    k1_c.checksum.length = sizeof(k1_c_data);
-    k1_c.checksum.data   = k1_c_data;
-
-    ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
-    if (ret)
-       krb5_abortx(context, "hmac failed");
-
-    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
-
-    k2_c.checksum.length = sizeof(k2_c_data);
-    k2_c.checksum.data   = k2_c_data;
-
-    ke.key = &kb;
-    kb.keyvalue = k2_c.checksum;
-
-    cksum.checksum.length = 16;
-    cksum.checksum.data   = data;
-
-    ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
-    if (ret)
-       krb5_abortx(context, "hmac failed");
-
-    ke.key = &kb;
-    kb.keyvalue = k1_c.checksum;
-
-    k3_c.checksum.length = sizeof(k3_c_data);
-    k3_c.checksum.data   = k3_c_data;
-
-    ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c);
-    if (ret)
-       krb5_abortx(context, "hmac failed");
-
-    EVP_CIPHER_CTX_init(&ctx);
-
-    EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
-    EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
-    EVP_CIPHER_CTX_cleanup(&ctx);
-
-    memset (k1_c_data, 0, sizeof(k1_c_data));
-    memset (k2_c_data, 0, sizeof(k2_c_data));
-    memset (k3_c_data, 0, sizeof(k3_c_data));
-    return 0;
-}
-
-static krb5_error_code
-ARCFOUR_subdecrypt(krb5_context context,
-                  struct key_data *key,
-                  void *data,
-                  size_t len,
-                  unsigned usage,
-                  void *ivec)
-{
-    EVP_CIPHER_CTX ctx;
-    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
-    Checksum k1_c, k2_c, k3_c, cksum;
-    struct key_data ke;
-    krb5_keyblock kb;
-    unsigned char t[4];
-    unsigned char *cdata = data;
-    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
-    unsigned char cksum_data[16];
-    krb5_error_code ret;
-
-    t[0] = (usage >>  0) & 0xFF;
-    t[1] = (usage >>  8) & 0xFF;
-    t[2] = (usage >> 16) & 0xFF;
-    t[3] = (usage >> 24) & 0xFF;
-
-    k1_c.checksum.length = sizeof(k1_c_data);
-    k1_c.checksum.data   = k1_c_data;
-
-    ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
-    if (ret)
-       krb5_abortx(context, "hmac failed");
-
-    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
-
-    k2_c.checksum.length = sizeof(k2_c_data);
-    k2_c.checksum.data   = k2_c_data;
-
-    ke.key = &kb;
-    kb.keyvalue = k1_c.checksum;
-
-    k3_c.checksum.length = sizeof(k3_c_data);
-    k3_c.checksum.data   = k3_c_data;
-
-    ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
-    if (ret)
-       krb5_abortx(context, "hmac failed");
-
-    EVP_CIPHER_CTX_init(&ctx);
-    EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
-    EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
-    EVP_CIPHER_CTX_cleanup(&ctx);
-
-    ke.key = &kb;
-    kb.keyvalue = k2_c.checksum;
-
-    cksum.checksum.length = 16;
-    cksum.checksum.data   = cksum_data;
-
-    ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
-    if (ret)
-       krb5_abortx(context, "hmac failed");
-
-    memset (k1_c_data, 0, sizeof(k1_c_data));
-    memset (k2_c_data, 0, sizeof(k2_c_data));
-    memset (k3_c_data, 0, sizeof(k3_c_data));
-
-    if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
-       krb5_clear_error_message (context);
-       return KRB5KRB_AP_ERR_BAD_INTEGRITY;
-    } else {
-       return 0;
-    }
-}
-
-/*
- * convert the usage numbers used in
- * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
- * draft-brezak-win2k-krb-rc4-hmac-04.txt
- */
-
-static krb5_error_code
-usage2arcfour (krb5_context context, unsigned *usage)
-{
-    switch (*usage) {
-    case KRB5_KU_AS_REP_ENC_PART : /* 3 */
-       *usage = 8;
-       return 0;
-    case KRB5_KU_USAGE_SEAL :  /* 22 */
-       *usage = 13;
-       return 0;
-    case KRB5_KU_USAGE_SIGN : /* 23 */
-        *usage = 15;
-        return 0;
-    case KRB5_KU_USAGE_SEQ: /* 24 */
-       *usage = 0;
-       return 0;
-    default :
-       return 0;
-    }
-}
-
-static krb5_error_code
-ARCFOUR_encrypt(krb5_context context,
-               struct key_data *key,
-               void *data,
-               size_t len,
-               krb5_boolean encryptp,
-               int usage,
-               void *ivec)
-{
-    krb5_error_code ret;
-    unsigned keyusage = usage;
-
-    if((ret = usage2arcfour (context, &keyusage)) != 0)
-       return ret;
-
-    if (encryptp)
-       return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
-    else
-       return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
-}
-
-
-/*
- *
- */
-
-static krb5_error_code
-AES_PRF(krb5_context context,
-       krb5_crypto crypto,
-       const krb5_data *in,
-       krb5_data *out)
-{
-    struct checksum_type *ct = crypto->et->checksum;
-    krb5_error_code ret;
-    Checksum result;
-    krb5_keyblock *derived;
-
-    result.cksumtype = ct->type;
-    ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
-    if (ret) {
-       krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
-       return ret;
+            ct = crypto->et->checksum;
     }
 
-    ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
-    if (ret) {
-       krb5_data_free(&result.checksum);
-       return ret;
+    if (ct == NULL) {
+       krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
+                               N_("checksum type not found", ""));
+        return KRB5_PROG_SUMTYPE_NOSUPP;
     }
 
-    if (result.checksum.length < crypto->et->blocksize)
-       krb5_abortx(context, "internal prf error");
+    *type = ct->type;
 
-    derived = NULL;
-    ret = krb5_derive_key(context, crypto->key.key,
-                         crypto->et->type, "prf", 3, &derived);
-    if (ret)
-       krb5_abortx(context, "krb5_derive_key");
+    return 0;
+}
 
-    ret = krb5_data_alloc(out, crypto->et->blocksize);
-    if (ret)
-       krb5_abortx(context, "malloc failed");
 
-    {
-       const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
-       EVP_CIPHER_CTX ctx;
-
-       EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */
-       EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1);
-       EVP_Cipher(&ctx, out->data, result.checksum.data,
-                  crypto->et->blocksize);
-       EVP_CIPHER_CTX_cleanup(&ctx);
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_checksumsize(krb5_context context,
+                 krb5_cksumtype type,
+                 size_t *size)
+{
+    struct checksum_type *ct = _krb5_find_checksum(type);
+    if(ct == NULL) {
+       krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
+                               N_("checksum type %d not supported", ""),
+                               type);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
     }
+    *size = ct->checksumsize;
+    return 0;
+}
 
-    krb5_data_free(&result.checksum);
-    krb5_free_keyblock(context, derived);
-
-    return ret;
+KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
+krb5_checksum_is_keyed(krb5_context context,
+                      krb5_cksumtype type)
+{
+    struct checksum_type *ct = _krb5_find_checksum(type);
+    if(ct == NULL) {
+       if (context)
+           krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
+                                   N_("checksum type %d not supported", ""),
+                                   type);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+    return ct->flags & F_KEYED;
 }
 
-/*
- * these should currently be in reverse preference order.
- * (only relevant for !F_PSEUDO) */
-
-static struct encryption_type enctype_null = {
-    ETYPE_NULL,
-    "null",
-    1,
-    1,
-    0,
-    &keytype_null,
-    &checksum_none,
-    NULL,
-    F_DISABLED,
-    NULL_encrypt,
-    0,
-    NULL
-};
-static struct encryption_type enctype_arcfour_hmac_md5 = {
-    ETYPE_ARCFOUR_HMAC_MD5,
-    "arcfour-hmac-md5",
-    1,
-    1,
-    8,
-    &keytype_arcfour,
-    &checksum_hmac_md5,
-    NULL,
-    F_SPECIAL,
-    ARCFOUR_encrypt,
-    0,
-    NULL
-};
-#ifdef DES3_OLD_ENCTYPE
-static struct encryption_type enctype_des3_cbc_md5 = {
-    ETYPE_DES3_CBC_MD5,
-    "des3-cbc-md5",
-    8,
-    8,
-    8,
-    &keytype_des3,
-    &checksum_rsa_md5,
-    &checksum_rsa_md5_des3,
-    0,
-    evp_encrypt,
-    0,
-    NULL
-};
-#endif
-static struct encryption_type enctype_des3_cbc_sha1 = {
-    ETYPE_DES3_CBC_SHA1,
-    "des3-cbc-sha1",
-    8,
-    8,
-    8,
-    &keytype_des3_derived,
-    &checksum_sha1,
-    &checksum_hmac_sha1_des3,
-    F_DERIVED,
-    evp_encrypt,
-    0,
-    NULL
-};
-#ifdef DES3_OLD_ENCTYPE
-static struct encryption_type enctype_old_des3_cbc_sha1 = {
-    ETYPE_OLD_DES3_CBC_SHA1,
-    "old-des3-cbc-sha1",
-    8,
-    8,
-    8,
-    &keytype_des3,
-    &checksum_sha1,
-    &checksum_hmac_sha1_des3,
-    0,
-    evp_encrypt,
-    0,
-    NULL
-};
-#endif
-static struct encryption_type enctype_aes128_cts_hmac_sha1 = {
-    ETYPE_AES128_CTS_HMAC_SHA1_96,
-    "aes128-cts-hmac-sha1-96",
-    16,
-    1,
-    16,
-    &keytype_aes128,
-    &checksum_sha1,
-    &checksum_hmac_sha1_aes128,
-    F_DERIVED,
-    evp_encrypt_cts,
-    16,
-    AES_PRF
-};
-static struct encryption_type enctype_aes256_cts_hmac_sha1 = {
-    ETYPE_AES256_CTS_HMAC_SHA1_96,
-    "aes256-cts-hmac-sha1-96",
-    16,
-    1,
-    16,
-    &keytype_aes256,
-    &checksum_sha1,
-    &checksum_hmac_sha1_aes256,
-    F_DERIVED,
-    evp_encrypt_cts,
-    16,
-    AES_PRF
-};
-static struct encryption_type enctype_des3_cbc_none = {
-    ETYPE_DES3_CBC_NONE,
-    "des3-cbc-none",
-    8,
-    8,
-    0,
-    &keytype_des3_derived,
-    &checksum_none,
-    NULL,
-    F_PSEUDO,
-    evp_encrypt,
-    0,
-    NULL
-};
-#ifdef HEIM_WEAK_CRYPTO
-static struct encryption_type enctype_des_cbc_crc = {
-    ETYPE_DES_CBC_CRC,
-    "des-cbc-crc",
-    8,
-    8,
-    8,
-    &keytype_des,
-    &checksum_crc32,
-    NULL,
-    F_DISABLED|F_WEAK,
-    evp_des_encrypt_key_ivec,
-    0,
-    NULL
-};
-static struct encryption_type enctype_des_cbc_md4 = {
-    ETYPE_DES_CBC_MD4,
-    "des-cbc-md4",
-    8,
-    8,
-    8,
-    &keytype_des,
-    &checksum_rsa_md4,
-    &checksum_rsa_md4_des,
-    F_DISABLED|F_WEAK,
-    evp_des_encrypt_null_ivec,
-    0,
-    NULL
-};
-static struct encryption_type enctype_des_cbc_md5 = {
-    ETYPE_DES_CBC_MD5,
-    "des-cbc-md5",
-    8,
-    8,
-    8,
-    &keytype_des,
-    &checksum_rsa_md5,
-    &checksum_rsa_md5_des,
-    F_DISABLED|F_WEAK,
-    evp_des_encrypt_null_ivec,
-    0,
-    NULL
-};
-static struct encryption_type enctype_des_cbc_none = {
-    ETYPE_DES_CBC_NONE,
-    "des-cbc-none",
-    8,
-    8,
-    0,
-    &keytype_des,
-    &checksum_none,
-    NULL,
-    F_PSEUDO|F_DISABLED|F_WEAK,
-    evp_des_encrypt_null_ivec,
-    0,
-    NULL
-};
-static struct encryption_type enctype_des_cfb64_none = {
-    ETYPE_DES_CFB64_NONE,
-    "des-cfb64-none",
-    1,
-    1,
-    0,
-    &keytype_des_old,
-    &checksum_none,
-    NULL,
-    F_PSEUDO|F_DISABLED|F_WEAK,
-    DES_CFB64_encrypt_null_ivec,
-    0,
-    NULL
-};
-static struct encryption_type enctype_des_pcbc_none = {
-    ETYPE_DES_PCBC_NONE,
-    "des-pcbc-none",
-    8,
-    8,
-    0,
-    &keytype_des_old,
-    &checksum_none,
-    NULL,
-    F_PSEUDO|F_DISABLED|F_WEAK,
-    DES_PCBC_encrypt_key_ivec,
-    0,
-    NULL
-};
-#endif /* HEIM_WEAK_CRYPTO */
-
-static struct encryption_type *etypes[] = {
-    &enctype_aes256_cts_hmac_sha1,
-    &enctype_aes128_cts_hmac_sha1,
-    &enctype_des3_cbc_sha1,
-    &enctype_des3_cbc_none, /* used by the gss-api mech */
-    &enctype_arcfour_hmac_md5,
-#ifdef DES3_OLD_ENCTYPE
-    &enctype_des3_cbc_md5,
-    &enctype_old_des3_cbc_sha1,
-#endif
-#ifdef HEIM_WEAK_CRYPTO
-    &enctype_des_cbc_crc,
-    &enctype_des_cbc_md4,
-    &enctype_des_cbc_md5,
-    &enctype_des_cbc_none,
-    &enctype_des_cfb64_none,
-    &enctype_des_pcbc_none,
-#endif
-    &enctype_null
-};
+KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
+krb5_checksum_is_collision_proof(krb5_context context,
+                                krb5_cksumtype type)
+{
+    struct checksum_type *ct = _krb5_find_checksum(type);
+    if(ct == NULL) {
+       if (context)
+           krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
+                                   N_("checksum type %d not supported", ""),
+                                   type);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+    return ct->flags & F_CPROOF;
+}
 
-static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_checksum_disable(krb5_context context,
+                     krb5_cksumtype type)
+{
+    struct checksum_type *ct = _krb5_find_checksum(type);
+    if(ct == NULL) {
+       if (context)
+           krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
+                                   N_("checksum type %d not supported", ""),
+                                   type);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+    ct->flags |= F_DISABLED;
+    return 0;
+}
 
+/************************************************************
+ *                                                          *
+ ************************************************************/
 
-static struct encryption_type *
-_find_enctype(krb5_enctype type)
+struct encryption_type *
+_krb5_find_enctype(krb5_enctype type)
 {
     int i;
-    for(i = 0; i < num_etypes; i++)
-       if(etypes[i]->type == type)
-           return etypes[i];
+    for(i = 0; i < _krb5_num_etypes; i++)
+       if(_krb5_etypes[i]->type == type)
+           return _krb5_etypes[i];
     return NULL;
 }
 
@@ -2786,7 +640,7 @@ krb5_enctype_to_string(krb5_context context,
                       char **string)
 {
     struct encryption_type *e;
-    e = _find_enctype(etype);
+    e = _krb5_find_enctype(etype);
     if(e == NULL) {
        krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
                                N_("encryption type %d not supported", ""),
@@ -2808,9 +662,9 @@ krb5_string_to_enctype(krb5_context context,
                       krb5_enctype *etype)
 {
     int i;
-    for(i = 0; i < num_etypes; i++)
-       if(strcasecmp(etypes[i]->name, string) == 0){
-           *etype = etypes[i]->type;
+    for(i = 0; i < _krb5_num_etypes; i++)
+       if(strcasecmp(_krb5_etypes[i]->name, string) == 0){
+           *etype = _krb5_etypes[i]->type;
            return 0;
        }
     krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
@@ -2824,7 +678,7 @@ krb5_enctype_to_keytype(krb5_context context,
                        krb5_enctype etype,
                        krb5_keytype *keytype)
 {
-    struct encryption_type *e = _find_enctype(etype);
+    struct encryption_type *e = _krb5_find_enctype(etype);
     if(e == NULL) {
        krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
                                N_("encryption type %d not supported", ""),
@@ -2839,7 +693,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enctype_valid(krb5_context context,
                   krb5_enctype etype)
 {
-    struct encryption_type *e = _find_enctype(etype);
+    struct encryption_type *e = _krb5_find_enctype(etype);
     if(e == NULL) {
        krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
                                N_("encryption type %d not supported", ""),
@@ -2877,11 +731,11 @@ krb5_cksumtype_to_enctype(krb5_context context,
 
     *etype = ETYPE_NULL;
 
-    for(i = 0; i < num_etypes; i++) {
-       if(etypes[i]->keyed_checksum &&
-          etypes[i]->keyed_checksum->type == ctype)
+    for(i = 0; i < _krb5_num_etypes; i++) {
+       if(_krb5_etypes[i]->keyed_checksum &&
+          _krb5_etypes[i]->keyed_checksum->type == ctype)
            {
-               *etype = etypes[i]->type;
+               *etype = _krb5_etypes[i]->type;
                return 0;
            }
     }
@@ -2897,7 +751,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_cksumtype_valid(krb5_context context,
                     krb5_cksumtype ctype)
 {
-    struct checksum_type *c = _find_checksum(ctype);
+    struct checksum_type *c = _krb5_find_checksum(ctype);
     if (c == NULL) {
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
                                N_("checksum type %d not supported", ""),
@@ -3977,85 +1831,12 @@ krb5_decrypt_EncryptedData(krb5_context context,
  *                                                          *
  ************************************************************/
 
-#define ENTROPY_NEEDED 128
-
-static int
-seed_something(void)
-{
-    char buf[1024], seedfile[256];
-
-    /* If there is a seed file, load it. But such a file cannot be trusted,
-       so use 0 for the entropy estimate */
-    if (RAND_file_name(seedfile, sizeof(seedfile))) {
-       int fd;
-       fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
-       if (fd >= 0) {
-           ssize_t ret;
-           rk_cloexec(fd);
-           ret = read(fd, buf, sizeof(buf));
-           if (ret > 0)
-               RAND_add(buf, ret, 0.0);
-           close(fd);
-       } else
-           seedfile[0] = '\0';
-    } else
-       seedfile[0] = '\0';
-
-    /* Calling RAND_status() will try to use /dev/urandom if it exists so
-       we do not have to deal with it. */
-    if (RAND_status() != 1) {
-#ifndef _WIN32
-       krb5_context context;
-       const char *p;
-
-       /* Try using egd */
-       if (!krb5_init_context(&context)) {
-           p = krb5_config_get_string(context, NULL, "libdefaults",
-                                      "egd_socket", NULL);
-           if (p != NULL)
-               RAND_egd_bytes(p, ENTROPY_NEEDED);
-           krb5_free_context(context);
-       }
-#else
-       /* TODO: Once a Windows CryptoAPI RAND method is defined, we
-          can use that and failover to another method. */
-#endif
-    }
-
-    if (RAND_status() == 1)    {
-       /* Update the seed file */
-       if (seedfile[0])
-           RAND_write_file(seedfile);
-
-       return 0;
-    } else
-       return -1;
-}
-
-KRB5_LIB_FUNCTION void KRB5_LIB_CALL
-krb5_generate_random_block(void *buf, size_t len)
-{
-    static int rng_initialized = 0;
-
-    HEIMDAL_MUTEX_lock(&crypto_mutex);
-    if (!rng_initialized) {
-       if (seed_something())
-           krb5_abortx(NULL, "Fatal: could not seed the "
-                       "random number generator");
-       
-       rng_initialized = 1;
-    }
-    HEIMDAL_MUTEX_unlock(&crypto_mutex);
-    if (RAND_bytes(buf, len) <= 0)
-       krb5_abortx(NULL, "Failed to generate random block");
-}
-
-static krb5_error_code
-derive_key(krb5_context context,
-          struct encryption_type *et,
-          struct key_data *key,
-          const void *constant,
-          size_t len)
+krb5_error_code
+_krb5_derive_key(krb5_context context,
+                struct encryption_type *et,
+                struct key_data *key,
+                const void *constant,
+                size_t len)
 {
     unsigned char *k = NULL;
     unsigned int nblocks = 0, i;
@@ -4117,7 +1898,7 @@ derive_key(krb5_context context,
     /* XXX keytype dependent post-processing */
     switch(kt->type) {
     case KEYTYPE_DES3:
-       DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
+       _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
        break;
     case KEYTYPE_AES128:
     case KEYTYPE_AES256:
@@ -4170,7 +1951,7 @@ krb5_derive_key(krb5_context context,
 
     *derived_key = NULL;
 
-    et = _find_enctype (etype);
+    et = _krb5_find_enctype (etype);
     if (et == NULL) {
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
                               N_("encryption type %d not supported", ""),
@@ -4183,10 +1964,10 @@ krb5_derive_key(krb5_context context,
        return ret;
 
     d.schedule = NULL;
-    ret = derive_key(context, et, &d, constant, constant_len);
+    ret = _krb5_derive_key(context, et, &d, constant, constant_len);
     if (ret == 0)
        ret = krb5_copy_keyblock(context, d.key, derived_key);
-    free_key_data(context, &d, et);
+    _krb5_free_key_data(context, &d, et);
     return ret;
 }
 
@@ -4212,7 +1993,7 @@ _get_derived_key(krb5_context context,
     }
     krb5_copy_keyblock(context, crypto->key.key, &d->key);
     _krb5_put_int(constant, usage, 5);
-    derive_key(context, crypto->et, d, constant, sizeof(constant));
+    _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant));
     *key = d;
     return 0;
 }
@@ -4249,7 +2030,7 @@ krb5_crypto_init(krb5_context context,
     }
     if(etype == ETYPE_NULL)
        etype = key->keytype;
-    (*crypto)->et = _find_enctype(etype);
+    (*crypto)->et = _krb5_find_enctype(etype);
     if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
        free(*crypto);
        *crypto = NULL;
@@ -4288,8 +2069,8 @@ free_key_schedule(krb5_context context,
     krb5_free_data(context, key->schedule);
 }
 
-static void
-free_key_data(krb5_context context, struct key_data *key,
+void
+_krb5_free_key_data(krb5_context context, struct key_data *key,
              struct encryption_type *et)
 {
     krb5_free_keyblock(context, key->key);
@@ -4303,7 +2084,7 @@ static void
 free_key_usage(krb5_context context, struct key_usage *ku,
               struct encryption_type *et)
 {
-    free_key_data(context, &ku->key, et);
+    _krb5_free_key_data(context, &ku->key, et);
 }
 
 /**
@@ -4326,7 +2107,7 @@ krb5_crypto_destroy(krb5_context context,
     for(i = 0; i < crypto->num_key_usage; i++)
        free_key_usage(context, &crypto->key_usage[i], crypto->et);
     free(crypto->key_usage);
-    free_key_data(context, &crypto->key, crypto->et);
+    _krb5_free_key_data(context, &crypto->key, crypto->et);
     free (crypto);
     return 0;
 }
@@ -4431,7 +2212,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enctype_disable(krb5_context context,
                     krb5_enctype enctype)
 {
-    struct encryption_type *et = _find_enctype(enctype);
+    struct encryption_type *et = _krb5_find_enctype(enctype);
     if(et == NULL) {
        if (context)
            krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
@@ -4458,7 +2239,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enctype_enable(krb5_context context,
                    krb5_enctype enctype)
 {
-    struct encryption_type *et = _find_enctype(enctype);
+    struct encryption_type *et = _krb5_find_enctype(enctype);
     if(et == NULL) {
        if (context)
            krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
@@ -4487,80 +2268,16 @@ krb5_allow_weak_crypto(krb5_context context,
 {
     int i;
 
-    for(i = 0; i < num_etypes; i++)
-       if(etypes[i]->flags & F_WEAK) {
+    for(i = 0; i < _krb5_num_etypes; i++)
+       if(_krb5_etypes[i]->flags & F_WEAK) {
            if(enable)
-               etypes[i]->flags &= ~F_DISABLED;
+               _krb5_etypes[i]->flags &= ~F_DISABLED;
            else
-               etypes[i]->flags |= F_DISABLED;
+               _krb5_etypes[i]->flags |= F_DISABLED;
        }
     return 0;
 }
 
-
-KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
-krb5_string_to_key_derived(krb5_context context,
-                          const void *str,
-                          size_t len,
-                          krb5_enctype etype,
-                          krb5_keyblock *key)
-{
-    struct encryption_type *et = _find_enctype(etype);
-    krb5_error_code ret;
-    struct key_data kd;
-    size_t keylen;
-    u_char *tmp;
-
-    if(et == NULL) {
-       krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
-                               N_("encryption type %d not supported", ""),
-                               etype);
-       return KRB5_PROG_ETYPE_NOSUPP;
-    }
-    keylen = et->keytype->bits / 8;
-
-    ALLOC(kd.key, 1);
-    if(kd.key == NULL) {
-       krb5_set_error_message (context, ENOMEM,
-                               N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
-    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
-    if(ret) {
-       free(kd.key);
-       return ret;
-    }
-    kd.key->keytype = etype;
-    tmp = malloc (keylen);
-    if(tmp == NULL) {
-       krb5_free_keyblock(context, kd.key);
-       krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
-    ret = _krb5_n_fold(str, len, tmp, keylen);
-    if (ret) {
-       free(tmp);
-       krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
-       return ret;
-    }
-    kd.schedule = NULL;
-    DES3_random_to_key(context, kd.key, tmp, keylen);
-    memset(tmp, 0, keylen);
-    free(tmp);
-    ret = derive_key(context,
-                    et,
-                    &kd,
-                    "kerberos", /* XXX well known constant */
-                    strlen("kerberos"));
-    if (ret) {
-       free_key_data(context, &kd, et);
-       return ret;
-    }
-    ret = krb5_copy_keyblock_contents(context, kd.key, key);
-    free_key_data(context, &kd, et);
-    return ret;
-}
-
 static size_t
 wrapped_length (krb5_context context,
                krb5_crypto  crypto,
@@ -4678,7 +2395,7 @@ krb5_random_to_key(krb5_context context,
                   krb5_keyblock *key)
 {
     krb5_error_code ret;
-    struct encryption_type *et = _find_enctype(type);
+    struct encryption_type *et = _krb5_find_enctype(type);
     if(et == NULL) {
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
                               N_("encryption type %d not supported", ""),
@@ -4705,261 +2422,6 @@ krb5_random_to_key(krb5_context context,
     return 0;
 }
 
-krb5_error_code
-_krb5_pk_octetstring2key(krb5_context context,
-                        krb5_enctype type,
-                        const void *dhdata,
-                        size_t dhsize,
-                        const heim_octet_string *c_n,
-                        const heim_octet_string *k_n,
-                        krb5_keyblock *key)
-{
-    struct encryption_type *et = _find_enctype(type);
-    krb5_error_code ret;
-    size_t keylen, offset;
-    void *keydata;
-    unsigned char counter;
-    unsigned char shaoutput[SHA_DIGEST_LENGTH];
-    EVP_MD_CTX *m;
-
-    if(et == NULL) {
-       krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
-                              N_("encryption type %d not supported", ""),
-                              type);
-       return KRB5_PROG_ETYPE_NOSUPP;
-    }
-    keylen = (et->keytype->bits + 7) / 8;
-
-    keydata = malloc(keylen);
-    if (keydata == NULL) {
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
-
-    m = EVP_MD_CTX_create();
-    if (m == NULL) {
-       free(keydata);
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
-
-    counter = 0;
-    offset = 0;
-    do {
-       
-       EVP_DigestInit_ex(m, EVP_sha1(), NULL);
-       EVP_DigestUpdate(m, &counter, 1);
-       EVP_DigestUpdate(m, dhdata, dhsize);
-
-       if (c_n)
-           EVP_DigestUpdate(m, c_n->data, c_n->length);
-       if (k_n)
-           EVP_DigestUpdate(m, k_n->data, k_n->length);
-
-       EVP_DigestFinal_ex(m, shaoutput, NULL);
-
-       memcpy((unsigned char *)keydata + offset,
-              shaoutput,
-              min(keylen - offset, sizeof(shaoutput)));
-
-       offset += sizeof(shaoutput);
-       counter++;
-    } while(offset < keylen);
-    memset(shaoutput, 0, sizeof(shaoutput));
-
-    EVP_MD_CTX_destroy(m);
-
-    ret = krb5_random_to_key(context, type, keydata, keylen, key);
-    memset(keydata, 0, sizeof(keylen));
-    free(keydata);
-    return ret;
-}
-
-static krb5_error_code
-encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
-{
-    KRB5PrincipalName pn;
-    krb5_error_code ret;
-    size_t size;
-
-    pn.principalName = p->name;
-    pn.realm = p->realm;
-
-    ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
-                      &pn, &size, ret);
-    if (ret) {
-       krb5_data_zero(data);
-       krb5_set_error_message(context, ret,
-                              N_("Failed to encode KRB5PrincipalName", ""));
-       return ret;
-    }
-    if (data->length != size)
-       krb5_abortx(context, "asn1 compiler internal error");
-    return 0;
-}
-
-static krb5_error_code
-encode_otherinfo(krb5_context context,
-                const AlgorithmIdentifier *ai,
-                krb5_const_principal client,
-                krb5_const_principal server,
-                krb5_enctype enctype,
-                const krb5_data *as_req,
-                const krb5_data *pk_as_rep,
-                const Ticket *ticket,
-                krb5_data *other)
-{
-    PkinitSP80056AOtherInfo otherinfo;
-    PkinitSuppPubInfo pubinfo;
-    krb5_error_code ret;
-    krb5_data pub;
-    size_t size;
-
-    krb5_data_zero(other);
-    memset(&otherinfo, 0, sizeof(otherinfo));
-    memset(&pubinfo, 0, sizeof(pubinfo));
-
-    pubinfo.enctype = enctype;
-    pubinfo.as_REQ = *as_req;
-    pubinfo.pk_as_rep = *pk_as_rep;
-    pubinfo.ticket = *ticket;
-    ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
-                      &pubinfo, &size, ret);
-    if (ret) {
-       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
-       return ret;
-    }
-    if (pub.length != size)
-       krb5_abortx(context, "asn1 compiler internal error");
-
-    ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
-    if (ret) {
-       free(pub.data);
-       return ret;
-    }
-    ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
-    if (ret) {
-       free(otherinfo.partyUInfo.data);
-       free(pub.data);
-       return ret;
-    }
-
-    otherinfo.algorithmID = *ai;
-    otherinfo.suppPubInfo = &pub;
-
-    ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
-                      &otherinfo, &size, ret);
-    free(otherinfo.partyUInfo.data);
-    free(otherinfo.partyVInfo.data);
-    free(pub.data);
-    if (ret) {
-       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
-       return ret;
-    }
-    if (other->length != size)
-       krb5_abortx(context, "asn1 compiler internal error");
-
-    return 0;
-}
-
-krb5_error_code
-_krb5_pk_kdf(krb5_context context,
-            const struct AlgorithmIdentifier *ai,
-            const void *dhdata,
-            size_t dhsize,
-            krb5_const_principal client,
-            krb5_const_principal server,
-            krb5_enctype enctype,
-            const krb5_data *as_req,
-            const krb5_data *pk_as_rep,
-            const Ticket *ticket,
-            krb5_keyblock *key)
-{
-    struct encryption_type *et;
-    krb5_error_code ret;
-    krb5_data other;
-    size_t keylen, offset;
-    uint32_t counter;
-    unsigned char *keydata;
-    unsigned char shaoutput[SHA_DIGEST_LENGTH];
-    EVP_MD_CTX *m;
-
-    if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) != 0) {
-       krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
-                              N_("KDF not supported", ""));
-       return KRB5_PROG_ETYPE_NOSUPP;
-    }
-    if (ai->parameters != NULL &&
-       (ai->parameters->length != 2 ||
-        memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
-       {
-           krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
-                                  N_("kdf params not NULL or the NULL-type",
-                                     ""));
-           return KRB5_PROG_ETYPE_NOSUPP;
-       }
-
-    et = _find_enctype(enctype);
-    if(et == NULL) {
-       krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
-                              N_("encryption type %d not supported", ""),
-                              enctype);
-       return KRB5_PROG_ETYPE_NOSUPP;
-    }
-    keylen = (et->keytype->bits + 7) / 8;
-
-    keydata = malloc(keylen);
-    if (keydata == NULL) {
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
-
-    ret = encode_otherinfo(context, ai, client, server,
-                          enctype, as_req, pk_as_rep, ticket, &other);
-    if (ret) {
-       free(keydata);
-       return ret;
-    }
-
-    m = EVP_MD_CTX_create();
-    if (m == NULL) {
-       free(keydata);
-       free(other.data);
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
-
-    offset = 0;
-    counter = 1;
-    do {
-       unsigned char cdata[4];
-       
-       EVP_DigestInit_ex(m, EVP_sha1(), NULL);
-       _krb5_put_int(cdata, counter, 4);
-       EVP_DigestUpdate(m, cdata, 4);
-       EVP_DigestUpdate(m, dhdata, dhsize);
-       EVP_DigestUpdate(m, other.data, other.length);
-
-       EVP_DigestFinal_ex(m, shaoutput, NULL);
-
-       memcpy((unsigned char *)keydata + offset,
-              shaoutput,
-              min(keylen - offset, sizeof(shaoutput)));
-
-       offset += sizeof(shaoutput);
-       counter++;
-    } while(offset < keylen);
-    memset(shaoutput, 0, sizeof(shaoutput));
-
-    EVP_MD_CTX_destroy(m);
-    free(other.data);
-
-    ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
-    memset(keydata, 0, sizeof(keylen));
-    free(keydata);
-
-    return ret;
-}
 
 
 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
@@ -4967,7 +2429,7 @@ krb5_crypto_prf_length(krb5_context context,
                       krb5_enctype type,
                       size_t *length)
 {
-    struct encryption_type *et = _find_enctype(type);
+    struct encryption_type *et = _krb5_find_enctype(type);
 
     if(et == NULL || et->prf_length == 0) {
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
@@ -5136,10 +2598,10 @@ krb5_keytype_to_enctypes (krb5_context context,
     unsigned n = 0;
     krb5_enctype *ret;
 
-    for (i = num_etypes - 1; i >= 0; --i) {
-       if (etypes[i]->keytype->type == keytype
-           && !(etypes[i]->flags & F_PSEUDO)
-           && krb5_enctype_valid(context, etypes[i]->type) == 0)
+    for (i = _krb5_num_etypes - 1; i >= 0; --i) {
+       if (_krb5_etypes[i]->keytype->type == keytype
+           && !(_krb5_etypes[i]->flags & F_PSEUDO)
+           && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
            ++n;
     }
     if (n == 0) {
@@ -5154,11 +2616,11 @@ krb5_keytype_to_enctypes (krb5_context context,
        return ENOMEM;
     }
     n = 0;
-    for (i = num_etypes - 1; i >= 0; --i) {
-       if (etypes[i]->keytype->type == keytype
-           && !(etypes[i]->flags & F_PSEUDO)
-           && krb5_enctype_valid(context, etypes[i]->type) == 0)
-           ret[n++] = etypes[i]->type;
+    for (i = _krb5_num_etypes - 1; i >= 0; --i) {
+       if (_krb5_etypes[i]->keytype->type == keytype
+           && !(_krb5_etypes[i]->flags & F_PSEUDO)
+           && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
+           ret[n++] = _krb5_etypes[i]->type;
     }
     *len = n;
     *val = ret;
@@ -5178,8 +2640,8 @@ krb5_enctypes_compatible_keys(krb5_context context,
                              krb5_enctype etype1,
                              krb5_enctype etype2)
 {
-    struct encryption_type *e1 = _find_enctype(etype1);
-    struct encryption_type *e2 = _find_enctype(etype2);
+    struct encryption_type *e1 = _krb5_find_enctype(etype1);
+    struct encryption_type *e2 = _krb5_find_enctype(etype2);
     return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
 }
 
index c4c202be5db92fe7ddc294bc44675e974f00f08c..f62a5532ab6050ecfb941b0d15293ad6d64f2c5d 100644 (file)
@@ -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);
+}
index 8f9d46219023b500607782cd93f8ba3b39b0cd75..9e06770e64f0646da00f99dd2a34519be65898a7 100644 (file)
 #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,
index 2fdb76d757b0e3633f601bbd30b45f589344d718..d8d038e7bbc7a77db91b78cafea66069da9e0f0f 100644 (file)
@@ -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"
index b76c1b584dca4dc4574ed350092a63068687b388..733d20f174829b0aef11746d23433aed1dce4f07 100644 (file)
@@ -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;
+}
index 7ed91b0768ca270aaa7237fbf738193d29717158..93489b607b3b71cde906c900b39bbd112bbe5d9b 100644 (file)
@@ -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);
index 69d9879330e0678d2fa27700e06b20af7d45599f..d50052c8bcb3c5499e3b106d4a3b26c8a68630b4 100644 (file)
@@ -75,6 +75,43 @@ struct krb5_pac_data {
 
 static const char zeros[PAC_ALIGNMENT] = { 0 };
 
+/*
+ * HMAC-MD5 checksum over any key (needed for the PAC routines)
+ */
+
+static krb5_error_code
+HMAC_MD5_any_checksum(krb5_context context,
+                     const krb5_keyblock *key,
+                     const void *data,
+                     size_t len,
+                     unsigned usage,
+                     Checksum *result)
+{
+    struct key_data local_key;
+    krb5_error_code ret;
+
+    memset(&local_key, 0, sizeof(local_key));
+
+    ret = krb5_copy_keyblock(context, key, &local_key.key);
+    if (ret)
+       return ret;
+
+    ret = krb5_data_alloc (&result->checksum, 16);
+    if (ret) {
+       krb5_free_keyblock(context, local_key.key);
+       return ret;
+    }
+
+    result->cksumtype = CKSUMTYPE_HMAC_MD5;
+    ret = _krb5_HMAC_MD5_checksum(context, &local_key, data, len, usage, result);
+    if (ret)
+       krb5_data_free(&result->checksum);
+
+    krb5_free_keyblock(context, local_key.key);
+    return ret;
+}
+
+
 /*
  *
  */
@@ -90,15 +127,13 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len,
 
     p = calloc(1, sizeof(*p));
     if (p == NULL) {
-       ret = ENOMEM;
-       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+       ret = _krb5_enomem(context);
        goto out;
     }
 
     sp = krb5_storage_from_readonly_mem(ptr, len);
     if (sp == NULL) {
-       ret = ENOMEM;
-       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+       ret = _krb5_enomem(context);
        goto out;
     }
     krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
@@ -121,8 +156,7 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len,
     p->pac = calloc(1,
                    sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (tmp - 1)));
     if (p->pac == NULL) {
-       ret = ENOMEM;
-       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+       ret = _krb5_enomem(context);
        goto out;
     }
 
@@ -232,26 +266,22 @@ krb5_pac_init(krb5_context context, krb5_pac *pac)
 
     p = calloc(1, sizeof(*p));
     if (p == NULL) {
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
+       return _krb5_enomem(context);
     }
 
     p->pac = calloc(1, sizeof(*p->pac));
     if (p->pac == NULL) {
        free(p);
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
+       return _krb5_enomem(context);
     }
 
     ret = krb5_data_alloc(&p->data, PACTYPE_SIZE);
     if (ret) {
        free (p->pac);
        free(p);
-       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
-       return ret;
+       return _krb5_enomem(context);
     }
 
-
     *pac = p;
     return 0;
 }
@@ -269,10 +299,9 @@ krb5_pac_add_buffer(krb5_context context, krb5_pac p,
 
     ptr = realloc(p->pac,
                  sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * len));
-    if (ptr == NULL) {
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
+    if (ptr == NULL)
+       return _krb5_enomem(context);
+
     p->pac = ptr;
 
     for (i = 0; i < len; i++)
@@ -379,8 +408,7 @@ krb5_pac_get_types(krb5_context context,
     *types = calloc(p->pac->numbuffers, sizeof(*types));
     if (*types == NULL) {
        *len = 0;
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
+       return _krb5_enomem(context);
     }
     for (i = 0; i < p->pac->numbuffers; i++)
        (*types)[i] = p->pac->buffers[i].type;
@@ -421,10 +449,9 @@ verify_checksum(krb5_context context,
 
     sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo,
                               sig->buffersize);
-    if (sp == NULL) {
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
+    if (sp == NULL)
+       return _krb5_enomem(context);
+
     krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
 
     CHECK(ret, krb5_ret_uint32(sp, &type), out);
@@ -433,8 +460,7 @@ verify_checksum(krb5_context context,
        sig->buffersize - krb5_storage_seek(sp, 0, SEEK_CUR);
     cksum.checksum.data = malloc(cksum.checksum.length);
     if (cksum.checksum.data == NULL) {
-       ret = ENOMEM;
-       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+       ret = _krb5_enomem(context);
        goto out;
     }
     ret = krb5_storage_read(sp, cksum.checksum.data, cksum.checksum.length);
@@ -459,20 +485,23 @@ verify_checksum(krb5_context context,
      * for the same issue in MIT, and
      * http://blogs.msdn.com/b/openspecification/archive/2010/01/01/verifying-the-server-signature-in-kerberos-privilege-account-certificate.aspx
      * for Microsoft's explaination */
+
     if (cksum.cksumtype == CKSUMTYPE_HMAC_MD5) {
        Checksum local_checksum;
 
-       ret = HMAC_MD5_any_checksum(context, key, ptr, len, KRB5_KU_OTHER_CKSUM, &local_checksum);
+       memset(&local_checksum, 0, sizeof(local_checksum));
 
-       if(local_checksum.checksum.length != cksum.checksum.length ||
-          ct_memcmp(local_checksum.checksum.data, cksum.checksum.data, local_checksum.checksum.length)) {
+       ret = HMAC_MD5_any_checksum(context, key, ptr, len,
+                                   KRB5_KU_OTHER_CKSUM, &local_checksum);
+
+       if (ret != 0 || krb5_data_ct_cmp(&local_checksum.checksum, &cksum.checksum) != 0) {
            ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
            krb5_set_error_message(context, ret,
-                                  N_("PAC integrity check failed for hmac-md5 checksum", ""));
-       } else {
-               ret = 0;
+                                  N_("PAC integrity check failed for "
+                                     "hmac-md5 checksum", ""));
        }
        krb5_data_free(&local_checksum.checksum);
+
    } else {
        krb5_crypto crypto = NULL;
 
@@ -516,8 +545,10 @@ create_checksum(krb5_context context,
      * for the same issue in MIT, and
      * http://blogs.msdn.com/b/openspecification/archive/2010/01/01/verifying-the-server-signature-in-kerberos-privilege-account-certificate.aspx
      * for Microsoft's explaination */
+
     if (cksumtype == CKSUMTYPE_HMAC_MD5) {
-       ret = HMAC_MD5_any_checksum(context, key, data, datalen, KRB5_KU_OTHER_CKSUM, &cksum);
+       ret = HMAC_MD5_any_checksum(context, key, data, datalen,
+                                   KRB5_KU_OTHER_CKSUM, &cksum);
     } else {
        ret = krb5_crypto_init(context, key, 0, &crypto);
        if (ret)
@@ -572,10 +603,8 @@ verify_logonname(krb5_context context,
 
     sp = krb5_storage_from_readonly_mem((const char *)data->data + logon_name->offset_lo,
                                        logon_name->buffersize);
-    if (sp == NULL) {
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
+    if (sp == NULL)
+       return _krb5_enomem(context);
 
     krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
 
@@ -602,8 +631,7 @@ verify_logonname(krb5_context context,
     s = malloc(len);
     if (s == NULL) {
        krb5_storage_free(sp);
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
+       return _krb5_enomem(context);
     }
     ret = krb5_storage_read(sp, s, len);
     if (ret != len) {
@@ -619,10 +647,9 @@ verify_logonname(krb5_context context,
        unsigned int flags = WIND_RW_LE;
 
        ucs2 = malloc(sizeof(ucs2[0]) * ucs2len);
-       if (ucs2 == NULL) {
-           krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-           return ENOMEM;
-       }
+       if (ucs2 == NULL)
+           return _krb5_enomem(context);
+
        ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len);
        free(s);
        if (ret) {
@@ -640,8 +667,7 @@ verify_logonname(krb5_context context,
        s = malloc(u8len);
        if (s == NULL) {
            free(ucs2);
-           krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-           return ENOMEM;
+           return _krb5_enomem(context);
        }
        ret = wind_ucs2utf8(ucs2, ucs2len, s, &u8len);
        free(ucs2);
@@ -687,10 +713,9 @@ build_logon_name(krb5_context context,
     krb5_data_zero(logon);
 
     sp = krb5_storage_emem();
-    if (sp == NULL) {
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
+    if (sp == NULL)
+       return _krb5_enomem(context);
+
     krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
 
     CHECK(ret, krb5_store_uint32(sp, t & 0xffffffff), out);
@@ -708,7 +733,7 @@ build_logon_name(krb5_context context,
 #if 1 /* cheat for now */
     s2 = malloc(len * 2);
     if (s2 == NULL) {
-       ret = ENOMEM;
+       ret = _krb5_enomem(context);
        free(s);
        goto out;
     }
@@ -724,7 +749,7 @@ build_logon_name(krb5_context context,
     ret = krb5_storage_write(sp, s2, len * 2);
     free(s2);
     if (ret != len * 2) {
-       ret = ENOMEM;
+       ret = _krb5_enomem(context);
        goto out;
     }
     ret = krb5_storage_to_data(sp, logon);
@@ -851,10 +876,9 @@ fill_zeros(krb5_context context, krb5_storage *sp, size_t len)
        if (l > sizeof(zeros))
            l = sizeof(zeros);
        sret = krb5_storage_write(sp, zeros, l);
-       if (sret <= 0) {
-           krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-           return ENOMEM;
-       }
+       if (sret <= 0)
+           return _krb5_enomem(context);
+
        len -= sret;
     }
     return 0;
@@ -924,10 +948,9 @@ _krb5_pac_sign(krb5_context context,
        void *ptr;
 
        ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (p->pac->numbuffers + num - 1)));
-       if (ptr == NULL) {
-           krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-           return ENOMEM;
-       }
+       if (ptr == NULL)
+           return _krb5_enomem(context);
+
        p->pac = ptr;
 
        if (p->logon_name == NULL) {
@@ -962,17 +985,15 @@ _krb5_pac_sign(krb5_context context,
 
     /* Encode PAC */
     sp = krb5_storage_emem();
-    if (sp == NULL) {
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
-    }
+    if (sp == NULL)
+       return _krb5_enomem(context);
+
     krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
 
     spdata = krb5_storage_emem();
     if (spdata == NULL) {
        krb5_storage_free(sp);
-       krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-       return ENOMEM;
+       return _krb5_enomem(context);
     }
     krb5_storage_set_flags(spdata, KRB5_STORAGE_BYTEORDER_LE);
 
@@ -1010,8 +1031,7 @@ _krb5_pac_sign(krb5_context context,
 
            sret = krb5_storage_write(spdata, ptr, len);
            if (sret != len) {
-               ret = ENOMEM;
-               krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+               ret = _krb5_enomem(context);
                goto out;
            }
            /* XXX if not aligned, fill_zeros */
@@ -1048,15 +1068,14 @@ _krb5_pac_sign(krb5_context context,
     ret = krb5_storage_write(sp, d.data, d.length);
     if (ret != d.length) {
        krb5_data_free(&d);
-       ret = ENOMEM;
-       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+       ret = _krb5_enomem(context);
        goto out;
     }
     krb5_data_free(&d);
 
     ret = krb5_storage_to_data(sp, &d);
     if (ret) {
-       krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+       ret = _krb5_enomem(context);
        goto out;
     }
 
index e19ba4a27cc3baedea591b7fcf48b9212fbdb29a..89be46c1aed838334cf1d6230164e409db4bf80f 100644 (file)
@@ -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;
+}
index 49e68ef177587ed7e85c4f1f8e78d5991984ea4c..0dedba3d72bf49d569c025f305084893e06fe178 100644 (file)
@@ -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.
  *
index 0fcc832e1fff4e4b097d4486473bbde2c11f789b..22e2142df88fdc71aec411668892351ef743db0e 100644 (file)
@@ -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 */
index 8390d79acc3c4e47bf408619e08a0b3189df93c2..1cc5c064451902317e9dfa01a61e0550e0fb5807 100644 (file)
@@ -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.
  *
@@ -1000,69 +1238,102 @@ int
 heim_ntlm_build_ntlm1_master(void *key, size_t len,
                             struct ntlm_buf *session,
                             struct ntlm_buf *master)
+{
+    struct ntlm_buf sess;
+    int ret;
+
+    ret = heim_ntlm_v1_base_session(key, len, &sess);
+    if (ret)
+       return ret;
+
+    ret = heim_ntlm_keyex_wrap(&sess, session, master);
+    heim_ntlm_free_buf(&sess);
+
+    return ret;
+}
+
+/**
+ * Generates an NTLMv2 session random with associated session master key.
+ *
+ * @param key the NTLMv2 key
+ * @param len length of key
+ * @param blob the NTLMv2 "blob"
+ * @param session generated session nonce, should be freed with heim_ntlm_free_buf().
+ * @param master calculated session master key, should be freed with heim_ntlm_free_buf().
+ *
+ * @return In case of success 0 is return, an errors, a errno in what
+ * went wrong.
+ *
+ * @ingroup ntlm_core
+ */
+
+
+int
+heim_ntlm_build_ntlm2_master(void *key, size_t len,
+                            struct ntlm_buf *blob,
+                            struct ntlm_buf *session,
+                            struct ntlm_buf *master)
+{
+    struct ntlm_buf sess;
+    int ret;
+
+    ret = heim_ntlm_v2_base_session(key, len, blob, &sess);
+    if (ret)
+       return ret;
+
+    ret = heim_ntlm_keyex_wrap(&sess, session, master);
+    heim_ntlm_free_buf(&sess);
+
+    return ret;
+}
+
+/**
+ * Given a key and encrypted session, unwrap the session key
+ *
+ * @param key the sessionBaseKey
+ * @param len length of key
+ * @param encryptedSession encrypted session, type3.session field.
+ * @param session generated session nonce, should be freed with heim_ntlm_free_buf().
+ *
+ * @return In case of success 0 is return, an errors, a errno in what
+ * went wrong.
+ *
+ * @ingroup ntlm_core
+ */
+
+int
+heim_ntlm_keyex_unwrap(struct ntlm_buf *baseKey,
+                      struct ntlm_buf *encryptedSession,
+                      struct ntlm_buf *session)
 {
     EVP_CIPHER_CTX c;
 
-    memset(master, 0, sizeof(*master));
     memset(session, 0, sizeof(*session));
 
-    if (len != MD4_DIGEST_LENGTH)
-       return EINVAL;
+    if (baseKey->length != MD4_DIGEST_LENGTH)
+       return HNTLM_ERR_INVALID_LENGTH;
 
     session->length = MD4_DIGEST_LENGTH;
     session->data = malloc(session->length);
     if (session->data == NULL) {
        session->length = 0;
-       return EINVAL;
-    }
-    master->length = MD4_DIGEST_LENGTH;
-    master->data = malloc(master->length);
-    if (master->data == NULL) {
-       heim_ntlm_free_buf(master);
-       heim_ntlm_free_buf(session);
-       return EINVAL;
+       return ENOMEM;
     }
-
     EVP_CIPHER_CTX_init(&c);
 
-    {
-       unsigned char sessionkey[MD4_DIGEST_LENGTH];
-       EVP_MD_CTX *m;
-
-       m = EVP_MD_CTX_create();
-       if (m == NULL) {
-           EVP_CIPHER_CTX_cleanup(&c);
-           heim_ntlm_free_buf(master);
-           heim_ntlm_free_buf(session);
-           return ENOMEM;
-       }
-
-       EVP_DigestInit_ex(m, EVP_md4(), NULL);
-       EVP_DigestUpdate(m, key, len);
-       EVP_DigestFinal_ex(m, sessionkey, NULL);
-       EVP_MD_CTX_destroy(m);
-       
-       if (EVP_CipherInit_ex(&c, EVP_rc4(), NULL, sessionkey, NULL, 1) != 1) {
-           EVP_CIPHER_CTX_cleanup(&c);
-           heim_ntlm_free_buf(master);
-           heim_ntlm_free_buf(session);
-           return EINVAL;
-       }
-    }
-
-    if (RAND_bytes(session->data, session->length) != 1) {
+    if (EVP_CipherInit_ex(&c, EVP_rc4(), NULL, baseKey->data, NULL, 0) != 1) {
        EVP_CIPHER_CTX_cleanup(&c);
-       heim_ntlm_free_buf(master);
        heim_ntlm_free_buf(session);
-       return EINVAL;
+       return HNTLM_ERR_CRYPTO;
     }
 
-    EVP_Cipher(&c, master->data, session->data, master->length);
+    EVP_Cipher(&c, session->data, encryptedSession->data, session->length);
     EVP_CIPHER_CTX_cleanup(&c);
 
     return 0;
 }
 
+
 /**
  * Generates an NTLMv2 session key.
  *
@@ -1134,6 +1405,54 @@ nt2unixtime(uint64_t t)
     return (time_t)t;
 }
 
+/**
+ * Calculate LMv2 response
+ *
+ * @param key the ntlm key
+ * @param len length of key
+ * @param username name of the user, as sent in the message, assumed to be in UTF8.
+ * @param target the name of the target, assumed to be in UTF8.
+ * @param serverchallenge challenge as sent by the server in the type2 message.
+ * @param infotarget infotarget as sent by the server in the type2 message.
+ * @param ntlmv2 calculated session key
+ * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf().
+ *
+ * @return In case of success 0 is return, an errors, a errno in what
+ * went wrong.
+ *
+ * @ingroup ntlm_core
+ */
+
+int
+heim_ntlm_calculate_lm2(const void *key, size_t len,
+                       const char *username,
+                       const char *target,
+                       const unsigned char serverchallenge[8],
+                       unsigned char ntlmv2[16],
+                       struct ntlm_buf *answer)
+{
+    unsigned char clientchallenge[8];
+
+    if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1)
+       return HNTLM_ERR_RAND;
+
+    /* calculate ntlmv2 key */
+
+    heim_ntlm_ntlmv2_key(key, len, username, target, ntlmv2);
+
+    answer->data = malloc(24);
+    if (answer->data == NULL)
+        return ENOMEM;
+    answer->length = 24;
+
+    heim_ntlm_derive_ntlm2_sess(ntlmv2, clientchallenge, 8,
+                               serverchallenge, answer->data);
+
+    memcpy(((uint8_t *)answer->data) + 16, clientchallenge, 8);
+
+    return 0;
+}
+
 
 /**
  * Calculate NTLMv2 response
@@ -1142,7 +1461,7 @@ nt2unixtime(uint64_t t)
  * @param len length of key
  * @param username name of the user, as sent in the message, assumed to be in UTF8.
  * @param target the name of the target, assumed to be in UTF8.
- * @param serverchallange challange as sent by the server in the type2 message.
+ * @param serverchallenge challenge as sent by the server in the type2 message.
  * @param infotarget infotarget as sent by the server in the type2 message.
  * @param ntlmv2 calculated session key
  * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf().
@@ -1157,24 +1476,22 @@ int
 heim_ntlm_calculate_ntlm2(const void *key, size_t len,
                          const char *username,
                          const char *target,
-                         const unsigned char serverchallange[8],
+                         const unsigned char serverchallenge[8],
                          const struct ntlm_buf *infotarget,
                          unsigned char ntlmv2[16],
                          struct ntlm_buf *answer)
 {
     krb5_error_code ret;
     krb5_data data;
-    unsigned int hmaclen;
     unsigned char ntlmv2answer[16];
     krb5_storage *sp;
-    unsigned char clientchallange[8];
-    HMAC_CTX c;
+    unsigned char clientchallenge[8];
     uint64_t t;
 
     t = unix2nttime(time(NULL));
 
-    if (RAND_bytes(clientchallange, sizeof(clientchallange)) != 1)
-       return EINVAL;
+    if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1)
+       return HNTLM_ERR_RAND;
 
     /* calculate ntlmv2 key */
 
@@ -1193,7 +1510,7 @@ heim_ntlm_calculate_ntlm2(const void *key, size_t len,
     CHECK(krb5_store_uint32(sp, t & 0xffffffff), 0);
     CHECK(krb5_store_uint32(sp, t >> 32), 0);
 
-    CHECK(krb5_storage_write(sp, clientchallange, 8), 8);
+    CHECK(krb5_storage_write(sp, clientchallenge, 8), 8);
 
     CHECK(krb5_store_uint32(sp, 0), 0);  /* unknown but zero will work */
     CHECK(krb5_storage_write(sp, infotarget->data, infotarget->length),
@@ -1204,12 +1521,7 @@ heim_ntlm_calculate_ntlm2(const void *key, size_t len,
     krb5_storage_free(sp);
     sp = NULL;
 
-    HMAC_CTX_init(&c);
-    HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL);
-    HMAC_Update(&c, serverchallange, 8);
-    HMAC_Update(&c, data.data, data.length);
-    HMAC_Final(&c, ntlmv2answer, &hmaclen);
-    HMAC_CTX_cleanup(&c);
+    heim_ntlm_derive_ntlm2_sess(ntlmv2, data.data, data.length, serverchallenge, ntlmv2answer);
 
     sp = krb5_storage_emem();
     if (sp == NULL) {
@@ -1245,7 +1557,7 @@ static const int authtimediff = 3600 * 2; /* 2 hours */
  * @param username name of the user, as sent in the message, assumed to be in UTF8.
  * @param target the name of the target, assumed to be in UTF8.
  * @param now the time now (0 if the library should pick it up itself)
- * @param serverchallange challange as sent by the server in the type2 message.
+ * @param serverchallenge challenge as sent by the server in the type2 message.
  * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf().
  * @param infotarget infotarget as sent by the server in the type2 message.
  * @param ntlmv2 calculated session key
@@ -1261,27 +1573,25 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
                       const char *username,
                       const char *target,
                       time_t now,
-                      const unsigned char serverchallange[8],
+                      const unsigned char serverchallenge[8],
                       const struct ntlm_buf *answer,
                       struct ntlm_buf *infotarget,
                       unsigned char ntlmv2[16])
 {
     krb5_error_code ret;
-    unsigned int hmaclen;
     unsigned char clientanswer[16];
     unsigned char clientnonce[8];
     unsigned char serveranswer[16];
     krb5_storage *sp;
-    HMAC_CTX c;
-    uint64_t t;
     time_t authtime;
     uint32_t temp;
+    uint64_t t;
 
     infotarget->length = 0;
     infotarget->data = NULL;
 
     if (answer->length < 16)
-       return EINVAL;
+       return HNTLM_ERR_INVALID_LENGTH;
 
     if (now == 0)
        now = time(NULL);
@@ -1312,11 +1622,11 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
     authtime = nt2unixtime(t);
 
     if (abs((int)(authtime - now)) > authtimediff) {
-       ret = EINVAL;
+       ret = HNTLM_ERR_TIME_SKEW;
        goto out;
     }
 
-    /* client challange */
+    /* client challenge */
     CHECK(krb5_storage_read(sp, clientnonce, 8), 8);
 
     CHECK(krb5_ret_uint32(sp, &temp), 0); /* unknown */
@@ -1334,16 +1644,19 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
     krb5_storage_free(sp);
     sp = NULL;
 
-    HMAC_CTX_init(&c);
-    HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL);
-    HMAC_Update(&c, serverchallange, 8);
-    HMAC_Update(&c, ((unsigned char *)answer->data) + 16, answer->length - 16);
-    HMAC_Final(&c, serveranswer, &hmaclen);
-    HMAC_CTX_cleanup(&c);
+    if (answer->length < 16) {
+       ret = HNTLM_ERR_INVALID_LENGTH;
+       goto out;
+    }
+
+    heim_ntlm_derive_ntlm2_sess(ntlmv2,
+                               ((unsigned char *)answer->data) + 16, answer->length - 16,
+                               serverchallenge,
+                               serveranswer);
 
     if (memcmp(serveranswer, clientanswer, 16) != 0) {
        heim_ntlm_free_buf(infotarget);
-       return EINVAL;
+       return HNTLM_ERR_AUTH;
     }
 
     return 0;
@@ -1377,24 +1690,24 @@ heim_ntlm_calculate_ntlm2_sess(const unsigned char clnt_nonce[8],
                               struct ntlm_buf *lm,
                               struct ntlm_buf *ntlm)
 {
-    unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH];
+    unsigned char ntlm2_sess_hash[8];
     unsigned char res[21], *resp;
-    EVP_MD_CTX *m;
+    int code;
 
-    m = EVP_MD_CTX_create();
-    if (m == NULL)
-       return ENOMEM;
+    code = heim_ntlm_calculate_ntlm2_sess_hash(clnt_nonce, svr_chal,
+                                              ntlm2_sess_hash);
+    if (code) {
+       return code;
+    }
 
     lm->data = malloc(24);
     if (lm->data == NULL) {
-       EVP_MD_CTX_destroy(m);
        return ENOMEM;
     }
     lm->length = 24;
 
     ntlm->data = malloc(24);
     if (ntlm->data == NULL) {
-       EVP_MD_CTX_destroy(m);
        free(lm->data);
        lm->data = NULL;
        return ENOMEM;
@@ -1405,12 +1718,6 @@ heim_ntlm_calculate_ntlm2_sess(const unsigned char clnt_nonce[8],
     memset(lm->data, 0, 24);
     memcpy(lm->data, clnt_nonce, 8);
 
-    EVP_DigestInit_ex(m, EVP_md5(), NULL);
-    EVP_DigestUpdate(m, svr_chal, 8); /* session nonce part 1 */
-    EVP_DigestUpdate(m, clnt_nonce, 8); /* session nonce part 2 */
-    EVP_DigestFinal_ex(m, ntlm2_sess_hash, NULL); /* will only use first 8 bytes */
-    EVP_MD_CTX_destroy(m);
-
     memset(res, 0, sizeof(res));
     memcpy(res, ntlm_hash, 16);
 
@@ -1421,3 +1728,73 @@ heim_ntlm_calculate_ntlm2_sess(const unsigned char clnt_nonce[8],
 
     return 0;
 }
+
+
+/*
+ * Calculate the NTLM2 Session "Verifier"
+ *
+ * @param clnt_nonce client nonce
+ * @param svr_chal server challage
+ * @param hash The NTLM session verifier
+ *
+ * @return In case of success 0 is return, an errors, a errno in what
+ * went wrong.
+ *
+ * @ingroup ntlm_core
+ */
+
+int
+heim_ntlm_calculate_ntlm2_sess_hash(const unsigned char clnt_nonce[8],
+                                   const unsigned char svr_chal[8],
+                                   unsigned char verifier[8])
+{
+    unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH];
+    EVP_MD_CTX *m;
+
+    m = EVP_MD_CTX_create();
+    if (m == NULL)
+       return ENOMEM;
+
+    EVP_DigestInit_ex(m, EVP_md5(), NULL);
+    EVP_DigestUpdate(m, svr_chal, 8); /* session nonce part 1 */
+    EVP_DigestUpdate(m, clnt_nonce, 8); /* session nonce part 2 */
+    EVP_DigestFinal_ex(m, ntlm2_sess_hash, NULL); /* will only use first 8 bytes */
+    EVP_MD_CTX_destroy(m);
+
+    memcpy(verifier, ntlm2_sess_hash, 8);
+
+    return 0;
+}
+
+
+/*
+ * Derive a NTLM2 session key
+ *
+ * @param sessionkey session key from domain controller
+ * @param clnt_nonce client nonce
+ * @param svr_chal server challenge
+ * @param derivedkey salted session key
+ *
+ * @return In case of success 0 is return, an errors, a errno in what
+ * went wrong.
+ *
+ * @ingroup ntlm_core
+ */
+
+void
+heim_ntlm_derive_ntlm2_sess(const unsigned char sessionkey[16],
+                           const unsigned char *clnt_nonce, size_t clnt_nonce_length,
+                           const unsigned char svr_chal[8],
+                           unsigned char derivedkey[16])
+{
+    unsigned int hmaclen;
+    HMAC_CTX c;
+
+    /* HMAC(Ksession, serverchallenge || clientchallenge) */
+    HMAC_CTX_init(&c);
+    HMAC_Init_ex(&c, sessionkey, 16, EVP_md5(), NULL);
+    HMAC_Update(&c, svr_chal, 8);
+    HMAC_Update(&c, clnt_nonce, clnt_nonce_length);
+    HMAC_Final(&c, derivedkey, &hmaclen);
+    HMAC_CTX_cleanup(&c);
+}