├── .travis.yml
├── Makefile
├── README.md
├── arg_parser
├── Makefile
├── arg_parser.c
├── arg_parser.h
└── arg_parser_example.c
├── config
├── Makefile
├── genpass-example.ini
├── ini.c
└── ini.h
├── defaults.md
├── encoders
├── Makefile
├── b10.c
├── b10.h
├── b64.c
├── b64.h
├── base16.c
├── base16.h
├── base91.c
├── base91.h
├── encoders.c
├── encoders.h
├── skey.c
├── skey.h
├── z85.c
└── z85.h
├── genpass.c
├── genpass.gif
├── getpass
├── libscrypt
├── LICENSE
├── Makefile
├── README.md
├── b10.c
├── b10.h
├── b64.c
├── b64.h
├── crypto-mcf.c
├── crypto-scrypt-saltgen.c
├── crypto_scrypt-check.c
├── crypto_scrypt-hash.c
├── crypto_scrypt-hexconvert.c
├── crypto_scrypt-hexconvert.h
├── crypto_scrypt-nosse.c
├── libscrypt.h
├── libscrypt.version
├── main.c
├── sha256.c
├── sha256.h
├── skey.c
├── skey.h
├── slowequals.c
├── slowequals.h
├── sysendian.h
├── z85.c
└── z85.h
├── man
├── genpass.1
└── getpass.1
├── poison
└── poison.h
├── readpass
├── Makefile
├── readpass.c
├── readpass.h
├── warn.c
└── warn.h
└── test
├── README.md
├── genpass-mp-input.exp.sh
├── genpass-name-and-mp-input.exp.sh
├── genpass-normal-input.exp.sh
├── genpass-registration-mode.exp.sh
├── genpass-site-and-mp-input.exp.sh
├── genpass-static.db
├── getpass.db
└── test.sh
/.travis.yml:
--------------------------------------------------------------------------------
1 | before_install:
2 | - sudo apt-get update
3 | #expect is required for testing genpass
4 | #xvfb, xclip and notify* are required for testing getpass
5 | - sudo apt-get install -y build-essential expect xclip notify-osd libnotify-bin
6 | script: make test
7 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | PREFIX ?= /usr/local
2 | LIBDIR ?= $(PREFIX)/lib
3 | INCLUDEDIR ?= $(PREFIX)/include
4 | MAKE_DIR ?= install -d
5 | INSTALL_DATA ?= install
6 |
7 | CC?=gcc
8 | CFLAGS?=-O2 -Wall -g -fno-builtin-memset
9 | LDFLAGS?=-Wl,-z,now -Wl,-z,relro -Wl,-soname,libscrypt.so.0 -Wl,--version-script=libscrypt.version
10 | CFLAGS_EXTRA?=-Wl,-rpath=.
11 |
12 | SHELL=/bin/sh
13 |
14 | all: genpass
15 |
16 | deps:
17 | @for dir in *; do \
18 | if [ -f $$dir/Makefile ]; then \
19 | echo "processing $$dir/"; \
20 | $(MAKE) -C $$dir || exit 1; \
21 | fi; \
22 | done;
23 |
24 | genpass: deps genpass.o
25 | $(CC) -o genpass genpass.o arg_parser/arg_parser.o config/ini.o \
26 | readpass/readpass.o encoders/*.o \
27 | $(CFLAGS_EXTRA) -L./libscrypt/ -lscrypt
28 | $(CC) -static -o genpass-static genpass.o \
29 | arg_parser/arg_parser.o config/ini.o readpass/readpass.o \
30 | encoders/*.o \
31 | $(CFLAGS_EXTRA) -L./libscrypt/ -lscrypt
32 |
33 | dist: all
34 | strip genpass genpass-static
35 |
36 | clean:
37 | @for dir in *; do \
38 | if [ -f $$dir/Makefile ]; then \
39 | echo "processing $$dir/"; \
40 | $(MAKE) clean -C $$dir; \
41 | fi; \
42 | done;
43 | rm -f *.o genpass genpass-static
44 | rm -rf test/*.tmp
45 |
46 | test: all
47 | xvfb-run sh test/test.sh
48 |
49 | .PHONY: test
50 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## genpass
2 |
3 | [](https://travis-ci.org/javier-lopez/genpass)
4 |
5 | A stateless password generator.
6 |
7 |
8 |
9 |
10 |
11 | ## Quick start
12 |
13 | ### Ubuntu based systems (LTS versions)
14 |
15 | 1. Set up the minos archive:
16 |
17 | ```
18 | $ sudo add-apt-repository ppa:minos-archive/main
19 | ```
20 |
21 | 2. Install:
22 |
23 | ```
24 | $ sudo apt-get update && sudo apt-get install genpass
25 | ```
26 |
27 | ### Other Linux distributions
28 |
29 | 1. Compile from source
30 |
31 | ```
32 | $ make
33 | ```
34 |
35 | 2. Copy `genpass` or `genpass-static` to a system wide location or use directly
36 |
37 | ```
38 | $ cp genpass genpass-static /usr/local/bin/
39 | ```
40 |
41 | **Only for the dynamic genpass binary**
42 |
43 | 3. Install `libscrypt` from your prefered source. On Ubuntu/Debian it's named `libscrypt0`
44 |
45 | ```
46 | $ sudo apt-get install libscrypt0
47 | ```
48 |
49 | 3. Or use the bundled `./libscrypt/libscrypt.so.0` one.
50 |
51 | ```
52 | $ sudo cp ./libscrypt/libscrypt.so.0 /usr/lib/
53 | ```
54 |
55 | Linux static binaries can also be retrieved with [static-get](https://github.com/minos-org/minos-static), for x86|amd64 platforms
56 |
57 | 1. Fetch static binaries
58 |
59 | ```
60 | $ sh <(wget -qO- s.minos.io/s) -x genpass
61 | ```
62 |
63 | 2. Copy `genpass` or `genpass-static` to a system wide location or use directly
64 |
65 | ```
66 | $ cp genpass-*/genpass genpass-*/genpass-static /usr/local/bin/
67 | ```
68 |
69 | ## Usage
70 |
71 | First time usage:
72 |
73 | $ genpass
74 | Name: Guy Mann
75 | Site: github.com
76 | Master password: passwd #it won't be shown
77 | 4?Hs>Jf#r*X9>7rznOS?4L=ysh&X>M/?8F>?^P(hW
78 |
79 | This will prompt you for your name, site and master password. The first time it's executed it will take a relative long time (a couple of minutes) to get back. It'll create a cache key and will save it to `~/.genpass-cache`, then it will combine it with the master password and the site string to generate the final password. The cache key file should be guarded with moderate caution. If it gets leaked possible attackers may have an easier time guessing your master password (although it still will be considerably harder than average brute force attacks).
80 |
81 | General use
82 |
83 | $ genpass [options] [site]
84 |
85 | Because `genpass` hashes your (master password + url + name), you can use it to retrieve (regenerate) your passwords on any computer where it's installed.
86 |
87 | It's recommended to defined cost, length and other parameters explicitly, default values will change between versions as computers get updated on CPU/RAM.
88 |
89 | Default values for version `2016.10.30` are:
90 |
91 | Parameter | Value
92 | --------------------- | -------------
93 | Cache cost (Scrypt N) | 2^20
94 | Cost (Scrypt N) | 2^14
95 | Scrypt r | 8 bits
96 | Scrypt p | 16 bits
97 | Key length | 32 bytes, 256 bits
98 | Encoding | z85
99 |
100 | Past default values are listed in the [defaults.md](https://github.com/javier-lopez/genpass/blob/master/defaults.md) file.
101 |
102 | In addition, you can setup a configuration file using the `--config` option. An example is provided here: [genpass-example.ini](https://github.com/javier-lopez/genpass/blob/master/config/genpass-example.ini).
103 |
104 | ## Scheme
105 |
106 | The [scheme](https://www.cs.utexas.edu/~bwaters/publications/papers/www2005.pdf) uses two levels of hash computations (although with the -1 parameter it can use only one). The first level is executed once when a user begins to use a new machine for the first time. This computation is parameterized to take a relatively long time (around 60 seconds on this implementation) and its result are cached for future password calculations by the same user. The next level is used to compute site-specific passwords. It takes as input the calculation produced from the first level as well as the name of the site or account for which the user is interested, the computation time is parameterized to be fast (around .1 seconds in our implementation).
107 |
108 | Typical attackers (with access to a generated password but without a master password nor a cache key) will need to spend 60.1 seconds on average per try and will have little room for parallelization, legitimate users on the other hand will require 0.1s after the initial cache key is calculated. This way the scheme strives for the best balance between security and usability.
109 |
110 | The algorithm has been updated to use a key derivation function specifically designed to be computationally intensive on CPU, RAM and custom hardware attacks, [scrypt](http://www.tarsnap.com/scrypt/scrypt.pdf). The original paper uses a sha1 iteration logarithm which can be parallelized and is fast on modern [hardware](https://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1)(2010), fast is bad on key derived functions.
111 |
--------------------------------------------------------------------------------
/arg_parser/Makefile:
--------------------------------------------------------------------------------
1 | CC?=gcc
2 | CFLAGS?=-O2 -Wall -g
3 | LDFLAGS?=
4 | CFLAGS_EXTRA?=-Wl,-rpath=.
5 |
6 | all: arg_parser_example
7 |
8 | OBJS= arg_parser.o
9 |
10 | arg_parser_example: arg_parser.o
11 | $(CC) -Wall -static -o arg_parser_example arg_parser_example.c arg_parser.o $(CFLAGS_EXTRA) -L.
12 |
13 | clean:
14 | rm -f *.o arg_parser_example
15 |
--------------------------------------------------------------------------------
/arg_parser/arg_parser.c:
--------------------------------------------------------------------------------
1 | /* Arg_parser - POSIX/GNU command line argument parser. (C version)
2 | Copyright (C) 2006-2015 Antonio Diaz Diaz.
3 |
4 | This library is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 2 of the License, or
7 | (at your option) any later version.
8 |
9 | This library is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this library. If not, see .
16 |
17 | As a special exception, you may use this file as part of a free
18 | software library without restriction. Specifically, if other files
19 | instantiate templates or use macros or inline functions from this
20 | file, or you compile this file and link it with other files to
21 | produce an executable, this file does not by itself cause the
22 | resulting executable to be covered by the GNU General Public
23 | License. This exception does not however invalidate any other
24 | reasons why the executable file might be covered by the GNU General
25 | Public License.
26 | */
27 |
28 | #include
29 | #include
30 |
31 | #include "arg_parser.h"
32 |
33 |
34 | /* assure at least a minimum size for buffer 'buf' */
35 | static void * ap_resize_buffer( void * buf, const int min_size )
36 | {
37 | if( buf ) buf = realloc( buf, min_size );
38 | else buf = malloc( min_size );
39 | return buf;
40 | }
41 |
42 |
43 | static char push_back_record( struct Arg_parser * const ap,
44 | const int code, const char * const argument )
45 | {
46 | const int len = strlen( argument );
47 | struct ap_Record * p;
48 | void * tmp = ap_resize_buffer( ap->data,
49 | ( ap->data_size + 1 ) * sizeof (struct ap_Record) );
50 | if( !tmp ) return 0;
51 | ap->data = (struct ap_Record *)tmp;
52 | p = &(ap->data[ap->data_size]);
53 | p->code = code;
54 | p->argument = 0;
55 | tmp = ap_resize_buffer( p->argument, len + 1 );
56 | if( !tmp ) return 0;
57 | p->argument = (char *)tmp;
58 | strncpy( p->argument, argument, len + 1 );
59 | ++ap->data_size;
60 | return 1;
61 | }
62 |
63 |
64 | static char add_error( struct Arg_parser * const ap, const char * const msg )
65 | {
66 | const int len = strlen( msg );
67 | void * tmp = ap_resize_buffer( ap->error, ap->error_size + len + 1 );
68 | if( !tmp ) return 0;
69 | ap->error = (char *)tmp;
70 | strncpy( ap->error + ap->error_size, msg, len + 1 );
71 | ap->error_size += len;
72 | return 1;
73 | }
74 |
75 |
76 | static void free_data( struct Arg_parser * const ap )
77 | {
78 | int i;
79 | for( i = 0; i < ap->data_size; ++i ) free( ap->data[i].argument );
80 | if( ap->data ) { free( ap->data ); ap->data = 0; }
81 | ap->data_size = 0;
82 | }
83 |
84 |
85 | static char parse_long_option( struct Arg_parser * const ap,
86 | const char * const opt, const char * const arg,
87 | const struct ap_Option options[],
88 | int * const argindp )
89 | {
90 | unsigned len;
91 | int index = -1, i;
92 | char exact = 0, ambig = 0;
93 |
94 | for( len = 0; opt[len+2] && opt[len+2] != '='; ++len ) ;
95 |
96 | /* Test all long options for either exact match or abbreviated matches. */
97 | for( i = 0; options[i].code != 0; ++i )
98 | if( options[i].name && strncmp( options[i].name, &opt[2], len ) == 0 )
99 | {
100 | if( strlen( options[i].name ) == len ) /* Exact match found */
101 | { index = i; exact = 1; break; }
102 | else if( index < 0 ) index = i; /* First nonexact match found */
103 | else if( options[index].code != options[i].code ||
104 | options[index].has_arg != options[i].has_arg )
105 | ambig = 1; /* Second or later nonexact match found */
106 | }
107 |
108 | if( ambig && !exact )
109 | {
110 | add_error( ap, "option '" ); add_error( ap, opt );
111 | add_error( ap, "' is ambiguous" );
112 | return 1;
113 | }
114 |
115 | if( index < 0 ) /* nothing found */
116 | {
117 | add_error( ap, "unrecognized option '" ); add_error( ap, opt );
118 | add_error( ap, "'" );
119 | return 1;
120 | }
121 |
122 | ++*argindp;
123 |
124 | if( opt[len+2] ) /* '--=' syntax */
125 | {
126 | if( options[index].has_arg == ap_no )
127 | {
128 | add_error( ap, "option '--" ); add_error( ap, options[index].name );
129 | add_error( ap, "' doesn't allow an argument" );
130 | return 1;
131 | }
132 | if( options[index].has_arg == ap_yes && !opt[len+3] )
133 | {
134 | add_error( ap, "option '--" ); add_error( ap, options[index].name );
135 | add_error( ap, "' requires an argument" );
136 | return 1;
137 | }
138 | return push_back_record( ap, options[index].code, &opt[len+3] );
139 | }
140 |
141 | if( options[index].has_arg == ap_yes )
142 | {
143 | if( !arg || !arg[0] )
144 | {
145 | add_error( ap, "option '--" ); add_error( ap, options[index].name );
146 | add_error( ap, "' requires an argument" );
147 | return 1;
148 | }
149 | ++*argindp;
150 | return push_back_record( ap, options[index].code, arg );
151 | }
152 |
153 | return push_back_record( ap, options[index].code, "" );
154 | }
155 |
156 |
157 | static char parse_short_option( struct Arg_parser * const ap,
158 | const char * const opt, const char * const arg,
159 | const struct ap_Option options[],
160 | int * const argindp )
161 | {
162 | int cind = 1; /* character index in opt */
163 |
164 | while( cind > 0 )
165 | {
166 | int index = -1, i;
167 | const unsigned char code = opt[cind];
168 | char code_str[2];
169 | code_str[0] = code; code_str[1] = 0;
170 |
171 | if( code != 0 )
172 | for( i = 0; options[i].code; ++i )
173 | if( code == options[i].code )
174 | { index = i; break; }
175 |
176 | if( index < 0 )
177 | {
178 | add_error( ap, "invalid option -- '" ); add_error( ap, code_str );
179 | add_error( ap, "'" );
180 | return 1;
181 | }
182 |
183 | if( opt[++cind] == 0 ) { ++*argindp; cind = 0; } /* opt finished */
184 |
185 | if( options[index].has_arg != ap_no && cind > 0 && opt[cind] )
186 | {
187 | if( !push_back_record( ap, code, &opt[cind] ) ) return 0;
188 | ++*argindp; cind = 0;
189 | }
190 | else if( options[index].has_arg == ap_yes )
191 | {
192 | if( !arg || !arg[0] )
193 | {
194 | add_error( ap, "option '-" ); add_error( ap, code_str);
195 | add_error( ap, "' requires an argument" );
196 | return 1;
197 | }
198 | ++*argindp; cind = 0;
199 | if( !push_back_record( ap, code, arg ) ) return 0;
200 | }
201 | else if( !push_back_record( ap, code, "" ) ) return 0;
202 | }
203 | return 1;
204 | }
205 |
206 |
207 | char ap_init( struct Arg_parser * const ap,
208 | const int argc, const char * const argv[],
209 | const struct ap_Option options[], const char in_order )
210 | {
211 | const char ** non_options = 0; /* skipped non-options */
212 | int non_options_size = 0; /* number of skipped non-options */
213 | int argind = 1; /* index in argv */
214 | int i;
215 |
216 | ap->data = 0;
217 | ap->error = 0;
218 | ap->data_size = 0;
219 | ap->error_size = 0;
220 | if( argc < 2 || !argv || !options ) return 1;
221 |
222 | while( argind < argc )
223 | {
224 | const unsigned char ch1 = argv[argind][0];
225 | const unsigned char ch2 = ch1 ? argv[argind][1] : 0;
226 |
227 | if( ch1 == '-' && ch2 ) /* we found an option */
228 | {
229 | const char * const opt = argv[argind];
230 | const char * const arg = ( argind + 1 < argc ) ? argv[argind+1] : 0;
231 | if( ch2 == '-' )
232 | {
233 | if( !argv[argind][2] ) { ++argind; break; } /* we found "--" */
234 | else if( !parse_long_option( ap, opt, arg, options, &argind ) ) return 0;
235 | }
236 | else if( !parse_short_option( ap, opt, arg, options, &argind ) ) return 0;
237 | if( ap->error ) break;
238 | }
239 | else
240 | {
241 | if( !in_order )
242 | {
243 | void * tmp = ap_resize_buffer( non_options,
244 | ( non_options_size + 1 ) * sizeof *non_options );
245 | if( !tmp ) return 0;
246 | non_options = (const char **)tmp;
247 | non_options[non_options_size++] = argv[argind++];
248 | }
249 | else if( !push_back_record( ap, 0, argv[argind++] ) ) return 0;
250 | }
251 | }
252 | if( ap->error ) free_data( ap );
253 | else
254 | {
255 | for( i = 0; i < non_options_size; ++i )
256 | if( !push_back_record( ap, 0, non_options[i] ) ) return 0;
257 | while( argind < argc )
258 | if( !push_back_record( ap, 0, argv[argind++] ) ) return 0;
259 | }
260 | if( non_options ) free( non_options );
261 | return 1;
262 | }
263 |
264 |
265 | void ap_free( struct Arg_parser * const ap )
266 | {
267 | free_data( ap );
268 | if( ap->error ) { free( ap->error ); ap->error = 0; }
269 | ap->error_size = 0;
270 | }
271 |
272 |
273 | const char * ap_error( const struct Arg_parser * const ap )
274 | { return ap->error; }
275 |
276 |
277 | int ap_arguments( const struct Arg_parser * const ap )
278 | { return ap->data_size; }
279 |
280 |
281 | int ap_code( const struct Arg_parser * const ap, const int i )
282 | {
283 | if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].code;
284 | else return 0;
285 | }
286 |
287 |
288 | const char * ap_argument( const struct Arg_parser * const ap, const int i )
289 | {
290 | if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].argument;
291 | else return "";
292 | }
293 |
--------------------------------------------------------------------------------
/arg_parser/arg_parser.h:
--------------------------------------------------------------------------------
1 | /* Arg_parser - POSIX/GNU command line argument parser. (C version)
2 | Copyright (C) 2006-2015 Antonio Diaz Diaz.
3 |
4 | This library is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 2 of the License, or
7 | (at your option) any later version.
8 |
9 | This library is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this library. If not, see .
16 |
17 | As a special exception, you may use this file as part of a free
18 | software library without restriction. Specifically, if other files
19 | instantiate templates or use macros or inline functions from this
20 | file, or you compile this file and link it with other files to
21 | produce an executable, this file does not by itself cause the
22 | resulting executable to be covered by the GNU General Public
23 | License. This exception does not however invalidate any other
24 | reasons why the executable file might be covered by the GNU General
25 | Public License.
26 | */
27 |
28 | /* Arg_parser reads the arguments in 'argv' and creates a number of
29 | option codes, option arguments and non-option arguments.
30 |
31 | In case of error, 'ap_error' returns a non-null pointer to an error
32 | message.
33 |
34 | 'options' is an array of 'struct ap_Option' terminated by an element
35 | containing a code which is zero. A null name means a short-only
36 | option. A code value outside the unsigned char range means a
37 | long-only option.
38 |
39 | Arg_parser normally makes it appear as if all the option arguments
40 | were specified before all the non-option arguments for the purposes
41 | of parsing, even if the user of your program intermixed option and
42 | non-option arguments. If you want the arguments in the exact order
43 | the user typed them, call 'ap_init' with 'in_order' = true.
44 |
45 | The argument '--' terminates all options; any following arguments are
46 | treated as non-option arguments, even if they begin with a hyphen.
47 |
48 | The syntax for optional option arguments is '-'
49 | (without whitespace), or '--='.
50 | */
51 |
52 | #ifdef __cplusplus
53 | extern "C" {
54 | #endif
55 |
56 | enum ap_Has_arg { ap_no, ap_yes, ap_maybe };
57 |
58 | struct ap_Option
59 | {
60 | int code; /* Short option letter or code ( code != 0 ) */
61 | const char * name; /* Long option name (maybe null) */
62 | enum ap_Has_arg has_arg;
63 | };
64 |
65 |
66 | struct ap_Record
67 | {
68 | int code;
69 | char * argument;
70 | };
71 |
72 |
73 | struct Arg_parser
74 | {
75 | struct ap_Record * data;
76 | char * error;
77 | int data_size;
78 | int error_size;
79 | };
80 |
81 |
82 | char ap_init( struct Arg_parser * const ap,
83 | const int argc, const char * const argv[],
84 | const struct ap_Option options[], const char in_order );
85 |
86 | void ap_free( struct Arg_parser * const ap );
87 |
88 | const char * ap_error( const struct Arg_parser * const ap );
89 |
90 | /* The number of arguments parsed (may be different from argc) */
91 | int ap_arguments( const struct Arg_parser * const ap );
92 |
93 | /* If ap_code( i ) is 0, ap_argument( i ) is a non-option.
94 | Else ap_argument( i ) is the option's argument (or empty). */
95 | int ap_code( const struct Arg_parser * const ap, const int i );
96 |
97 | const char * ap_argument( const struct Arg_parser * const ap, const int i );
98 |
99 | #ifdef __cplusplus
100 | }
101 | #endif
102 |
--------------------------------------------------------------------------------
/arg_parser/arg_parser_example.c:
--------------------------------------------------------------------------------
1 | /* Exit status: 0 for a normal exit, 1 for environmental problems
2 | (file not found, invalid flags, I/O errors, etc), 2 to indicate a
3 | corrupt or invalid input file, 3 for an internal consistency error
4 | (eg, bug) which caused arg_parser to panic.
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | #include "arg_parser.h"
12 |
13 |
14 | static const char * const Program_name = "Arg_parser";
15 | static const char * const program_name = "arg_parser";
16 | static const char * const program_year = "2015";
17 | static const char * invocation_name = 0;
18 |
19 |
20 | void show_help( const char verbose )
21 | {
22 | printf( "%s - POSIX/GNU command line argument parser. (C version)\n", Program_name );
23 | printf( "See the source file 'cmain.c' to learn how to use %s in\n", Program_name );
24 | printf( "your own programs.\n"
25 | "\nUsage: %s [options]\n", invocation_name );
26 | printf( "\nOptions:\n"
27 | " -h, --help display this help and exit\n"
28 | " -V, --version output version information and exit\n"
29 | " -a, --append example of option with no argument\n"
30 | " -b, --block= example of option with required argument\n"
31 | " -c, --casual[=] example of option with optional argument\n"
32 | " -o example of short only option\n"
33 | " --orphan example of long only option\n"
34 | " -q, --quiet quiet operation\n"
35 | " -u, --uncaught example of intentional bug\n"
36 | " -v, --verbose verbose operation\n" );
37 | if( verbose )
38 | {
39 | printf( " -H, --hidden example of hidden option (shown with -v -h)\n" );
40 | }
41 | printf( "\nReport bugs to arg-parser-bug@nongnu.org\n"
42 | "Arg_parser home page: http://www.nongnu.org/arg-parser/arg_parser.html\n" );
43 | }
44 |
45 |
46 | void show_version()
47 | {
48 | printf( "%s \n", program_name );
49 | printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
50 | printf( "License GPLv2+: GNU GPL version 2 or later \n"
51 | "This is free software: you are free to change and redistribute it.\n"
52 | "There is NO WARRANTY, to the extent permitted by law.\n" );
53 | }
54 |
55 |
56 | void show_error( const char * const msg, const int errcode, const char help )
57 | {
58 | if( msg && msg[0] )
59 | {
60 | fprintf( stderr, "%s: %s", program_name, msg );
61 | if( errcode > 0 )
62 | fprintf( stderr, ": %s.", strerror( errcode ) );
63 | fprintf( stderr, "\n" );
64 | }
65 | if( help )
66 | fprintf( stderr, "Try '%s --help' for more information.\n",
67 | invocation_name );
68 | }
69 |
70 |
71 | void internal_error( const char * const msg )
72 | {
73 | fprintf( stderr, "%s: internal error: %s\n", program_name, msg );
74 | exit( 3 );
75 | }
76 |
77 |
78 | const char * optname( const int code, const struct ap_Option options[] )
79 | {
80 | static char buf[2] = "?";
81 | int i;
82 |
83 | if( code != 0 )
84 | for( i = 0; options[i].code; ++i )
85 | if( code == options[i].code )
86 | { if( options[i].name ) return options[i].name; else break; }
87 | if( code > 0 && code < 256 ) buf[0] = code; else buf[0] = '?';
88 | return buf;
89 | }
90 |
91 |
92 | int main( const int argc, const char * const argv[] )
93 | {
94 | char verbose = 0;
95 | const struct ap_Option options[] =
96 | {
97 | { 'a', "append", ap_no },
98 | { 'b', "block", ap_yes },
99 | { 'c', "casual", ap_maybe },
100 | { 'h', "help", ap_no },
101 | { 'H', "hidden", ap_no },
102 | { 'o', 0, ap_yes },
103 | { 'q', "quiet", ap_no },
104 | { 'u', "uncaught", ap_no },
105 | { 'v', "verbose", ap_no },
106 | { 'V', "version", ap_no },
107 | { 256, "orphan", ap_no },
108 | { 0, 0, ap_no } };
109 |
110 | struct Arg_parser parser;
111 | int argind;
112 | invocation_name = argv[0];
113 |
114 | if( !ap_init( &parser, argc, argv, options, 0 ) )
115 | { show_error( "Not enough memory.", 0, 0 ); return 1; }
116 | if( ap_error( &parser ) ) /* bad option */
117 | { show_error( ap_error( &parser ), 0, 1 ); return 1; }
118 |
119 | for( argind = 0; argind < ap_arguments( &parser ); ++argind )
120 | {
121 | const int code = ap_code( &parser, argind );
122 | if( !code ) break; /* no more options */
123 | switch( code )
124 | {
125 | case 'a': break; /* example, do nothing */
126 | case 'b': break; /* example, do nothing */
127 | case 'c': break; /* example, do nothing */
128 | case 'h': show_help( verbose ); return 0;
129 | case 'H': break; /* example, do nothing */
130 | case 'o': break; /* example, do nothing */
131 | case 'q': verbose = 0; break;
132 | /* case 'u': break; */ /* intentionally not caught */
133 | case 'v': verbose = 1; break;
134 | case 'V': show_version(); return 0;
135 | case 256: break; /* example, do nothing */
136 | default : internal_error( "uncaught option." );
137 | }
138 | } /* end process options */
139 |
140 | for( argind = 0; argind < ap_arguments( &parser ); ++argind )
141 | {
142 | const int code = ap_code( &parser, argind );
143 | const char * const arg = ap_argument( &parser, argind );
144 | if( code ) /* option */
145 | {
146 | const char * const name = optname( code, options );
147 | if( !name[1] )
148 | printf( "option '-%c'", name[0] );
149 | else
150 | printf( "option '--%s'", name );
151 | if( arg[0] )
152 | printf( " with argument '%s'", arg );
153 | }
154 | else /* non-option */
155 | printf( "non-option argument '%s'", arg );
156 | printf( "\n" );
157 | }
158 |
159 | if( !ap_arguments( &parser ) ) printf( "Hello, world!\n" );
160 |
161 | return 0;
162 | }
163 |
--------------------------------------------------------------------------------
/config/Makefile:
--------------------------------------------------------------------------------
1 | CC?=gcc
2 | CFLAGS?=-O2 -Wall -g
3 | LDFLAGS?=
4 | CFLAGS_EXTRA?=-Wl,-rpath=.
5 |
6 | all: ini
7 |
8 | OBJS= ini.o
9 |
10 | ini: ini.o
11 | $(CC) -Wall -static -c ini.c $(CFLAGS_EXTRA) -L.
12 |
13 | clean:
14 | rm -f *.o
15 |
--------------------------------------------------------------------------------
/config/genpass-example.ini:
--------------------------------------------------------------------------------
1 | ;This is a sample genpass configuration file.
2 | ;
3 | ;Even if the parameters are ommited then it will either take input
4 | ;from command line or default value will be assigned. (i.e it will
5 | ;proceed normally)
6 |
7 | [user] ; User Information
8 | name = "John Doe" ; name
9 | site = github.com ; site login
10 |
11 | [general] ; Genpass configuration
12 | cache_file = ~/.genpass-cache ; cache key file path
13 | keylen = 32 ; key length in bytes, "32" by default
14 | cache_cost = 20 ; cpu/memory cost for cache key, "20" by default
15 | cost = 14 ; cpu/memory cost for cache key, "14" by default
16 | scrypt_r = 8 ; block size, "8" by default (advanced)
17 | scrypt_p = 16 ; block size, "16" by default (advanced)
18 | encoding = z85 ; password encoding output, "z85" by default.
19 | ; supported values: dec|hex|base64|base91|z85|skey
20 |
--------------------------------------------------------------------------------
/config/ini.c:
--------------------------------------------------------------------------------
1 | /* inih -- simple .INI file parser
2 |
3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project
4 | home page for more info:
5 |
6 | https://github.com/benhoyt/inih
7 |
8 | */
9 |
10 | #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
11 | #define _CRT_SECURE_NO_WARNINGS
12 | #endif
13 |
14 | #include
15 | #include
16 | #include
17 |
18 | #include "ini.h"
19 |
20 | #if !INI_USE_STACK
21 | #include
22 | #endif
23 |
24 | #define MAX_SECTION 50
25 | #define MAX_NAME 50
26 |
27 | /* Strip whitespace chars off end of given string, in place. Return s. */
28 | static char* rstrip(char* s)
29 | {
30 | char* p = s + strlen(s);
31 | while (p > s && isspace((unsigned char)(*--p)))
32 | *p = '\0';
33 | return s;
34 | }
35 |
36 | /* Return pointer to first non-whitespace char in given string. */
37 | static char* lskip(const char* s)
38 | {
39 | while (*s && isspace((unsigned char)(*s)))
40 | s++;
41 | return (char*)s;
42 | }
43 |
44 | /* Return pointer to first char (of chars) or inline comment in given string,
45 | or pointer to null at end of string if neither found. Inline comment must
46 | be prefixed by a whitespace character to register as a comment. */
47 | static char* find_chars_or_comment(const char* s, const char* chars)
48 | {
49 | #if INI_ALLOW_INLINE_COMMENTS
50 | int was_space = 0;
51 | while (*s && (!chars || !strchr(chars, *s)) &&
52 | !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {
53 | was_space = isspace((unsigned char)(*s));
54 | s++;
55 | }
56 | #else
57 | while (*s && (!chars || !strchr(chars, *s))) {
58 | s++;
59 | }
60 | #endif
61 | return (char*)s;
62 | }
63 |
64 | /* Version of strncpy that ensures dest (size bytes) is null-terminated. */
65 | static char* strncpy0(char* dest, const char* src, size_t size)
66 | {
67 | strncpy(dest, src, size);
68 | dest[size - 1] = '\0';
69 | return dest;
70 | }
71 |
72 | /* See documentation in header file. */
73 | int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
74 | void* user)
75 | {
76 | /* Uses a fair bit of stack (use heap instead if you need to) */
77 | #if INI_USE_STACK
78 | char line[INI_MAX_LINE];
79 | #else
80 | char* line;
81 | #endif
82 | char section[MAX_SECTION] = "";
83 | char prev_name[MAX_NAME] = "";
84 |
85 | char* start;
86 | char* end;
87 | char* name;
88 | char* value;
89 | int lineno = 0;
90 | int error = 0;
91 |
92 | #if !INI_USE_STACK
93 | line = (char*)malloc(INI_MAX_LINE);
94 | if (!line) {
95 | return -2;
96 | }
97 | #endif
98 |
99 | /* Scan through stream line by line */
100 | while (reader(line, INI_MAX_LINE, stream) != NULL) {
101 | lineno++;
102 |
103 | start = line;
104 | #if INI_ALLOW_BOM
105 | if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
106 | (unsigned char)start[1] == 0xBB &&
107 | (unsigned char)start[2] == 0xBF) {
108 | start += 3;
109 | }
110 | #endif
111 | start = lskip(rstrip(start));
112 |
113 | if (*start == ';' || *start == '#') {
114 | /* Per Python configparser, allow both ; and # comments at the
115 | start of a line */
116 | }
117 | #if INI_ALLOW_MULTILINE
118 | else if (*prev_name && *start && start > line) {
119 | /* Non-blank line with leading whitespace, treat as continuation
120 | of previous name's value (as per Python configparser). */
121 | if (!handler(user, section, prev_name, start) && !error)
122 | error = lineno;
123 | }
124 | #endif
125 | else if (*start == '[') {
126 | /* A "[section]" line */
127 | end = find_chars_or_comment(start + 1, "]");
128 | if (*end == ']') {
129 | *end = '\0';
130 | strncpy0(section, start + 1, sizeof(section));
131 | *prev_name = '\0';
132 | }
133 | else if (!error) {
134 | /* No ']' found on section line */
135 | error = lineno;
136 | }
137 | }
138 | else if (*start) {
139 | /* Not a comment, must be a name[=:]value pair */
140 | end = find_chars_or_comment(start, "=:");
141 | if (*end == '=' || *end == ':') {
142 | *end = '\0';
143 | name = rstrip(start);
144 | value = lskip(end + 1);
145 | #if INI_ALLOW_INLINE_COMMENTS
146 | end = find_chars_or_comment(value, NULL);
147 | if (*end)
148 | *end = '\0';
149 | #endif
150 | rstrip(value);
151 |
152 | /* Valid name[=:]value pair found, call handler */
153 | strncpy0(prev_name, name, sizeof(prev_name));
154 | if (!handler(user, section, name, value) && !error)
155 | error = lineno;
156 | }
157 | else if (!error) {
158 | /* No '=' or ':' found on name[=:]value line */
159 | error = lineno;
160 | }
161 | }
162 |
163 | #if INI_STOP_ON_FIRST_ERROR
164 | if (error)
165 | break;
166 | #endif
167 | }
168 |
169 | #if !INI_USE_STACK
170 | free(line);
171 | #endif
172 |
173 | return error;
174 | }
175 |
176 | /* See documentation in header file. */
177 | int ini_parse_file(FILE* file, ini_handler handler, void* user)
178 | {
179 | return ini_parse_stream((ini_reader)fgets, file, handler, user);
180 | }
181 |
182 | /* See documentation in header file. */
183 | int ini_parse(const char* filename, ini_handler handler, void* user)
184 | {
185 | FILE* file;
186 | int error;
187 |
188 | file = fopen(filename, "r");
189 | if (!file)
190 | return -1;
191 | error = ini_parse_file(file, handler, user);
192 | fclose(file);
193 | return error;
194 | }
195 |
--------------------------------------------------------------------------------
/config/ini.h:
--------------------------------------------------------------------------------
1 | /* inih -- simple .INI file parser
2 |
3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project
4 | home page for more info:
5 |
6 | https://github.com/benhoyt/inih
7 |
8 | */
9 |
10 | #ifndef __INI_H__
11 | #define __INI_H__
12 |
13 | /* Make this header file easier to include in C++ code */
14 | #ifdef __cplusplus
15 | extern "C" {
16 | #endif
17 |
18 | #include
19 |
20 | /* Typedef for prototype of handler function. */
21 | typedef int (*ini_handler)(void* user, const char* section,
22 | const char* name, const char* value);
23 |
24 | /* Typedef for prototype of fgets-style reader function. */
25 | typedef char* (*ini_reader)(char* str, int num, void* stream);
26 |
27 | /* Parse given INI-style file. May have [section]s, name=value pairs
28 | (whitespace stripped), and comments starting with ';' (semicolon). Section
29 | is "" if name=value pair parsed before any section heading. name:value
30 | pairs are also supported as a concession to Python's configparser.
31 |
32 | For each name=value pair parsed, call handler function with given user
33 | pointer as well as section, name, and value (data only valid for duration
34 | of handler call). Handler should return nonzero on success, zero on error.
35 |
36 | Returns 0 on success, line number of first error on parse error (doesn't
37 | stop on first error), -1 on file open error, or -2 on memory allocation
38 | error (only when INI_USE_STACK is zero).
39 | */
40 | int ini_parse(const char* filename, ini_handler handler, void* user);
41 |
42 | /* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
43 | close the file when it's finished -- the caller must do that. */
44 | int ini_parse_file(FILE* file, ini_handler handler, void* user);
45 |
46 | /* Same as ini_parse(), but takes an ini_reader function pointer instead of
47 | filename. Used for implementing custom or string-based I/O. */
48 | int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
49 | void* user);
50 |
51 | /* Nonzero to allow multi-line value parsing, in the style of Python's
52 | configparser. If allowed, ini_parse() will call the handler with the same
53 | name for each subsequent line parsed. */
54 | #ifndef INI_ALLOW_MULTILINE
55 | #define INI_ALLOW_MULTILINE 1
56 | #endif
57 |
58 | /* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
59 | the file. See http://code.google.com/p/inih/issues/detail?id=21 */
60 | #ifndef INI_ALLOW_BOM
61 | #define INI_ALLOW_BOM 1
62 | #endif
63 |
64 | /* Nonzero to allow inline comments (with valid inline comment characters
65 | specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match
66 | Python 3.2+ configparser behaviour. */
67 | #ifndef INI_ALLOW_INLINE_COMMENTS
68 | #define INI_ALLOW_INLINE_COMMENTS 1
69 | #endif
70 | #ifndef INI_INLINE_COMMENT_PREFIXES
71 | #define INI_INLINE_COMMENT_PREFIXES ";"
72 | #endif
73 |
74 | /* Nonzero to use stack, zero to use heap (malloc/free). */
75 | #ifndef INI_USE_STACK
76 | #define INI_USE_STACK 1
77 | #endif
78 |
79 | /* Stop parsing on first error (default is to keep parsing). */
80 | #ifndef INI_STOP_ON_FIRST_ERROR
81 | #define INI_STOP_ON_FIRST_ERROR 0
82 | #endif
83 |
84 | /* Maximum line length for any line in INI file. */
85 | #ifndef INI_MAX_LINE
86 | #define INI_MAX_LINE 200
87 | #endif
88 |
89 | #ifdef __cplusplus
90 | }
91 | #endif
92 |
93 | #endif /* __INI_H__ */
94 |
--------------------------------------------------------------------------------
/defaults.md:
--------------------------------------------------------------------------------
1 | Default values for version `2016.10.30`:
2 | ----------------------------------------
3 |
4 | Parameter | Value
5 | --------------------- | -------------
6 | Cache cost (Scrypt N) | 2^20
7 | Cost (Scrypt N) | 2^14
8 | Scrypt r | 8 bits
9 | Scrypt p | 16 bits
10 | Key length | 32 bytes, 256 bits
11 | Encoding | z85
12 |
13 | ####IMPORTANT
14 | Due to bug https://github.com/javier-lopez/genpass/issues/2 passwords generated with older versions than `2016.10.30` will require to be updated them.
15 |
16 | Default values for version `2016.05.04`:
17 | ----------------------------------------
18 |
19 | Parameter | Value
20 | --------------------- | -------------
21 | Cache cost (Scrypt N) | 2^20
22 | Cost (Scrypt N) | 2^14
23 | Scrypt r | 8 bits
24 | Scrypt p | 16 bits
25 | Key length | 32 bytes, 256 bits
26 | Encoding | z85
27 |
28 | Default values for version `2016.01.01`:
29 | ----------------------------------------
30 |
31 | Parameter | Value
32 | --------------------- | -------------
33 | Cache cost (Scrypt N) | 2^20
34 | Cost (Scrypt N) | 2^10
35 | Scrypt r | 8 bits
36 | Scrypt p | 16 bits
37 | Key length | 32 bytes, 256 bits
38 | Encoding | z85
39 |
--------------------------------------------------------------------------------
/encoders/Makefile:
--------------------------------------------------------------------------------
1 | all: *.c
2 | $(CC) $(LDFLAGS) -I. -I../libscrypt/ -c $^
3 |
4 | clean:
5 | rm *.o
--------------------------------------------------------------------------------
/encoders/b10.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "crypto_scrypt-hexconvert.h"
9 |
10 | int libscrypt_b10_encode(src, srclength, target, targsize)
11 | unsigned char const *src;
12 | size_t srclength;
13 | char *target;
14 | size_t targsize;
15 | {
16 | size_t i;
17 | int len = 0;
18 |
19 | if (!src || srclength < 1 || targsize < (srclength * 2 + 1))
20 | return -1;
21 |
22 | memset(target, 0, targsize);
23 |
24 | for(i=0; i<=(srclength-1); i++)
25 | {
26 | /* snprintf(target, srclength,"%s...", target....) has undefined results
27 | * and can't be used. Using offests like this makes snprintf
28 | * nontrivial. we therefore have use inescure sprintf() and
29 | * lengths checked elsewhere (start of function) */
30 | /*@ -bufferoverflowhigh @*/
31 | len += sprintf(target+len, "%02u", (unsigned int) src[i]);
32 | }
33 |
34 | return 0;
35 |
36 | /*if (libscrypt_hex_encode(src, srclength, target, targsize) == -1) return -1;*/
37 | /*char *p;*/
38 | /*errno = 0;*/
39 | /*unsigned long int b10 = strtoul(target,&p,16);*/
40 |
41 | /*if (p == target) //no digits found*/
42 | /*return -1;*/
43 | /*else if ((b10 == LONG_MIN || b10 == ULONG_MAX) && errno == ERANGE)*/
44 | /*//value out of range*/
45 | /*return -1;*/
46 | /*else*/
47 | /*snprintf(target, targsize, "%ld", b10);*/
48 |
49 | /*return 0;*/
50 | }
51 |
--------------------------------------------------------------------------------
/encoders/b10.h:
--------------------------------------------------------------------------------
1 | int libscrypt_b10_encode(unsigned char const *src, size_t srclength,
2 | /*@out@*/ char *target, size_t targetsize);
3 |
--------------------------------------------------------------------------------
/encoders/b64.c:
--------------------------------------------------------------------------------
1 | /*Base64 encode/decode functions from OpenBSD (src/lib/libc/net/base64.c).*/
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "b64.h"
10 |
11 | static const char Base64Compliant[] =
12 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
13 | static const char Pad64Compliant = '=';
14 |
15 | static const char Base64[] =
16 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_";
17 | static const char Pad64 = '\0';
18 |
19 | /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
20 | The following encoding technique is taken from RFC 1521 by Borenstein
21 | and Freed. It is reproduced here in a slightly edited form for
22 | convenience.
23 |
24 | A 65-character subset of US-ASCII is used, enabling 6 bits to be
25 | represented per printable character. (The extra 65th character, "=",
26 | is used to signify a special processing function.)
27 |
28 | The encoding process represents 24-bit groups of input bits as output
29 | strings of 4 encoded characters. Proceeding from left to right, a
30 | 24-bit input group is formed by concatenating 3 8-bit input groups.
31 | These 24 bits are then treated as 4 concatenated 6-bit groups, each
32 | of which is translated into a single digit in the base64 alphabet.
33 |
34 | Each 6-bit group is used as an index into an array of 64 printable
35 | characters. The character referenced by the index is placed in the
36 | output string.
37 |
38 | Table 1: The Base64 Alphabet
39 |
40 | Value Encoding Value Encoding Value Encoding Value Encoding
41 | 0 A 17 R 34 i 51 z
42 | 1 B 18 S 35 j 52 0
43 | 2 C 19 T 36 k 53 1
44 | 3 D 20 U 37 l 54 2
45 | 4 E 21 V 38 m 55 3
46 | 5 F 22 W 39 n 56 4
47 | 6 G 23 X 40 o 57 5
48 | 7 H 24 Y 41 p 58 6
49 | 8 I 25 Z 42 q 59 7
50 | 9 J 26 a 43 r 60 8
51 | 10 K 27 b 44 s 61 9
52 | 11 L 28 c 45 t 62 +
53 | 12 M 29 d 46 u 63 /
54 | 13 N 30 e 47 v
55 | 14 O 31 f 48 w (pad) =
56 | 15 P 32 g 49 x
57 | 16 Q 33 h 50 y
58 |
59 | Special processing is performed if fewer than 24 bits are available
60 | at the end of the data being encoded. A full encoding quantum is
61 | always completed at the end of a quantity. When fewer than 24 input
62 | bits are available in an input group, zero bits are added (on the
63 | right) to form an integral number of 6-bit groups. Padding at the
64 | end of the data is performed using the '=' character.
65 |
66 | Since all base64 input is an integral number of octets, only the
67 | -------------------------------------------------
68 | following cases can arise:
69 |
70 | (1) the final quantum of encoding input is an integral
71 | multiple of 24 bits; here, the final unit of encoded
72 | output will be an integral multiple of 4 characters
73 | with no "=" padding,
74 | (2) the final quantum of encoding input is exactly 8 bits;
75 | here, the final unit of encoded output will be two
76 | characters followed by two "=" padding characters, or
77 | (3) the final quantum of encoding input is exactly 16 bits;
78 | here, the final unit of encoded output will be three
79 | characters followed by one "=" padding character.
80 | */
81 |
82 | int
83 | libscrypt_b64_encode(src, srclength, target, targsize)
84 | unsigned char const *src;
85 | size_t srclength;
86 | char *target;
87 | size_t targsize;
88 | {
89 | size_t datalength = 0;
90 | unsigned char input[3];
91 | unsigned char output[4];
92 | unsigned int i;
93 |
94 | memset(target, 0, targsize);
95 |
96 | while (2 < srclength) {
97 | input[0] = *src++;
98 | input[1] = *src++;
99 | input[2] = *src++;
100 | srclength -= 3;
101 |
102 | output[0] = input[0] >> 2;
103 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
104 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
105 | output[3] = input[2] & 0x3f;
106 |
107 | if (datalength + 4 > targsize)
108 | return (-1);
109 | target[datalength++] = Base64[output[0]];
110 | target[datalength++] = Base64[output[1]];
111 | target[datalength++] = Base64[output[2]];
112 | target[datalength++] = Base64[output[3]];
113 | }
114 |
115 | /* Now we worry about padding. */
116 | if (0 != srclength) {
117 | /* Get what's left. */
118 | input[0] = input[1] = input[2] = '\0';
119 | for (i = 0; i < srclength; i++)
120 | input[i] = *src++;
121 |
122 | output[0] = input[0] >> 2;
123 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
124 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
125 |
126 | if (datalength + 4 > targsize)
127 | return (-1);
128 | target[datalength++] = Base64[output[0]];
129 | target[datalength++] = Base64[output[1]];
130 | if (srclength == 1)
131 | target[datalength++] = Pad64;
132 | else
133 | target[datalength++] = Base64[output[2]];
134 | target[datalength++] = Pad64;
135 | }
136 | if (datalength >= targsize)
137 | return (-1);
138 | target[datalength] = '\0'; /* Returned value doesn't count \0. */
139 | return (int)(datalength);
140 | }
141 |
142 | int
143 | libscrypt_b64_encode_compliant(src, srclength, target, targsize)
144 | unsigned char const *src;
145 | size_t srclength;
146 | char *target;
147 | size_t targsize;
148 | {
149 | size_t datalength = 0;
150 | unsigned char input[3];
151 | unsigned char output[4];
152 | unsigned int i;
153 |
154 | memset(target, 0, targsize);
155 |
156 | while (2 < srclength) {
157 | input[0] = *src++;
158 | input[1] = *src++;
159 | input[2] = *src++;
160 | srclength -= 3;
161 |
162 | output[0] = input[0] >> 2;
163 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
164 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
165 | output[3] = input[2] & 0x3f;
166 |
167 | if (datalength + 4 > targsize)
168 | return (-1);
169 | target[datalength++] = Base64Compliant[output[0]];
170 | target[datalength++] = Base64Compliant[output[1]];
171 | target[datalength++] = Base64Compliant[output[2]];
172 | target[datalength++] = Base64Compliant[output[3]];
173 | }
174 |
175 | /* Now we worry about padding. */
176 | if (0 != srclength) {
177 | /* Get what's left. */
178 | input[0] = input[1] = input[2] = '\0';
179 | for (i = 0; i < srclength; i++)
180 | input[i] = *src++;
181 |
182 | output[0] = input[0] >> 2;
183 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
184 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
185 |
186 | if (datalength + 4 > targsize)
187 | return (-1);
188 | target[datalength++] = Base64Compliant[output[0]];
189 | target[datalength++] = Base64Compliant[output[1]];
190 | if (srclength == 1)
191 | target[datalength++] = Pad64Compliant;
192 | else
193 | target[datalength++] = Base64Compliant[output[2]];
194 | target[datalength++] = Pad64Compliant;
195 | }
196 | if (datalength >= targsize)
197 | return (-1);
198 | target[datalength] = '\0'; /* Returned value doesn't count \0. */
199 | return (int)(datalength);
200 | }
201 |
202 | /* skips all whitespace anywhere.
203 | converts characters, four at a time, starting at (or after)
204 | src from base - 64 numbers into three 8 bit bytes in the target area.
205 | it returns the number of data bytes stored at the target, or -1 on error.
206 | */
207 |
208 | int
209 | libscrypt_b64_decode_compliant(src, target, targsize)
210 | char const *src;
211 | unsigned char *target;
212 | size_t targsize;
213 | {
214 | int state, ch;
215 | unsigned int tarindex;
216 | unsigned char nextbyte;
217 | char *pos;
218 |
219 | state = 0;
220 | tarindex = 0;
221 |
222 | while ((ch = (unsigned char)*src++) != '\0') {
223 | if (isspace(ch)) /* Skip whitespace anywhere. */
224 | continue;
225 |
226 | if (ch == Pad64Compliant)
227 | break;
228 |
229 | pos = strchr(Base64Compliant, ch);
230 | if (pos == 0) /* A non-base64 character. */
231 | return (-1);
232 |
233 | switch (state) {
234 | case 0:
235 | if (target) {
236 | if (tarindex >= targsize)
237 | return (-1);
238 | target[tarindex] = (pos - Base64Compliant) << 2;
239 | }
240 | state = 1;
241 | break;
242 | case 1:
243 | if (target) {
244 | if (tarindex >= targsize)
245 | return (-1);
246 | target[tarindex] |= (pos - Base64Compliant) >> 4;
247 | nextbyte = ((pos - Base64Compliant) & 0x0f) << 4;
248 | if (tarindex + 1 < targsize)
249 | target[tarindex+1] = nextbyte;
250 | else if (nextbyte)
251 | return (-1);
252 | }
253 | tarindex++;
254 | state = 2;
255 | break;
256 | case 2:
257 | if (target) {
258 | if (tarindex >= targsize)
259 | return (-1);
260 | target[tarindex] |= (pos - Base64Compliant) >> 2;
261 | nextbyte = ((pos - Base64Compliant) & 0x03) << 6;
262 | if (tarindex + 1 < targsize)
263 | target[tarindex+1] = nextbyte;
264 | else if (nextbyte)
265 | return (-1);
266 | }
267 | tarindex++;
268 | state = 3;
269 | break;
270 | case 3:
271 | if (target) {
272 | if (tarindex >= targsize)
273 | return (-1);
274 | target[tarindex] |= (pos - Base64Compliant);
275 | }
276 | tarindex++;
277 | state = 0;
278 | break;
279 | }
280 | }
281 |
282 | /*
283 | * We are done decoding Base-64 chars. Let's see if we ended
284 | * on a byte boundary, and/or with erroneous trailing characters.
285 | */
286 |
287 | if (ch == Pad64Compliant) { /* We got a pad char. */
288 | ch = (unsigned char)*src++; /* Skip it, get next. */
289 | switch (state) {
290 | case 0: /* Invalid = in first position */
291 | case 1: /* Invalid = in second position */
292 | return (-1);
293 |
294 | case 2: /* Valid, means one byte of info */
295 | /* Skip any number of spaces. */
296 | for (; ch != '\0'; ch = (unsigned char)*src++)
297 | if (!isspace(ch))
298 | break;
299 | /* Make sure there is another trailing = sign. */
300 | if (ch != Pad64Compliant)
301 | return (-1);
302 | ch = (unsigned char)*src++; /* Skip the = */
303 | /* Fall through to "single trailing =" case. */
304 | /* FALLTHROUGH */
305 |
306 | case 3: /* Valid, means two bytes of info */
307 | /*
308 | * We know this char is an =. Is there anything but
309 | * whitespace after it?
310 | */
311 | for (; ch != '\0'; ch = (unsigned char)*src++)
312 | if (!isspace(ch))
313 | return (-1);
314 |
315 | /*
316 | * Now make sure for cases 2 and 3 that the "extra"
317 | * bits that slopped past the last full byte were
318 | * zeros. If we don't check them, they become a
319 | * subliminal channel.
320 | */
321 | if (target && tarindex < targsize &&
322 | target[tarindex] != 0)
323 | return (-1);
324 | }
325 | } else {
326 | /*
327 | * We ended by seeing the end of the string. Make sure we
328 | * have no partial bytes lying around.
329 | */
330 | if (state != 0)
331 | return (-1);
332 | }
333 |
334 | return (tarindex);
335 | }
336 |
--------------------------------------------------------------------------------
/encoders/b64.h:
--------------------------------------------------------------------------------
1 | /* BASE64 libraries used internally - should not need to be packaged */
2 | #include
3 | #define b64_encode_len(A) ((A+2)/3 * 4 + 1)
4 | #define b64_decode_len(A) (A / 4 * 3 + 2)
5 |
6 | //modified version, $_ instead of +/ and without '=' padding, optimized
7 | //for generating passwords
8 | int libscrypt_b64_encode(unsigned char const *src, size_t srclength,
9 | /*@out@*/ char *target, size_t targetsize);
10 |
11 | int libscrypt_b64_encode_compliant(unsigned char const *src, size_t srclength,
12 | /*@out@*/ char *target, size_t targetsize);
13 | int libscrypt_b64_decode_compliant(char const *src,
14 | /*@out@*/ unsigned char *target, size_t targetsize);
15 |
--------------------------------------------------------------------------------
/encoders/base16.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | /* The hexconvert function is only used to test reference vectors against
7 | * known answers. The contents of this file are therefore a component
8 | * to assist with test harnesses only
9 | */
10 |
11 | int libscrypt_hexconvert(const unsigned char * buf, size_t s, char *outbuf, size_t obs)
12 | {
13 | size_t i;
14 | int len = 0;
15 |
16 | if (!buf || s < 1 || obs < (s * 2 + 1))
17 | return 0;
18 |
19 | memset(outbuf, 0, obs);
20 |
21 | for(i=0; i<=(s-1); i++)
22 | {
23 | /* snprintf(outbuf, s,"%s...", outbuf....) has undefined results
24 | * and can't be used. Using offests like this makes snprintf
25 | * nontrivial. we therefore have use inescure sprintf() and
26 | * lengths checked elsewhere (start of function) */
27 | /*@ -bufferoverflowhigh @*/
28 | len += sprintf(outbuf+len, "%02x", (unsigned int) buf[i]);
29 | }
30 |
31 | return 1;
32 | }
33 |
34 | int libscrypt_hex_encode(const unsigned char * buf, size_t s, char *outbuf, size_t obs)
35 | {
36 | return libscrypt_hexconvert(buf, s, outbuf, obs);
37 | }
38 |
--------------------------------------------------------------------------------
/encoders/base16.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | /**
5 | * Converts a binary string to a hex representation of that string
6 | * outbuf must have size of at least buf * 2 + 1.
7 | */
8 | int libscrypt_hexconvert(const unsigned char * buf, size_t s, char *outbuf, size_t obs);
9 | int libscrypt_hex_encode(const unsigned char * buf, size_t s, char *outbuf, size_t obs);
10 |
--------------------------------------------------------------------------------
/encoders/base91.c:
--------------------------------------------------------------------------------
1 | /*
2 | * basE91 encoding/decoding routines
3 | *
4 | * Copyright (c) 2000-2006 Joachim Henke
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions are met:
9 | *
10 | * - Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * - Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * - Neither the name of Joachim Henke nor the names of his contributors may
16 | * be used to endorse or promote products derived from this software without
17 | * specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 | * POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | #include "base91.h"
33 |
34 | const unsigned char enctab[91] = {
35 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
36 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
37 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
38 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
39 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$',
40 | '%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=',
41 | '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"'
42 | };
43 | const unsigned char dectab[256] = {
44 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
45 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
46 | 91, 62, 90, 63, 64, 65, 66, 91, 67, 68, 69, 70, 71, 91, 72, 73,
47 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 74, 75, 76, 77, 78, 79,
48 | 80, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
49 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 81, 91, 82, 83, 84,
50 | 85, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
51 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 86, 87, 88, 89, 91,
52 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
53 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
54 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
55 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
56 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
57 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
58 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
59 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91
60 | };
61 |
62 | void basE91_init(struct basE91 *b)
63 | {
64 | b->queue = 0;
65 | b->nbits = 0;
66 | b->val = -1;
67 | }
68 |
69 | size_t basE91_encode(struct basE91 *b, const void *i, size_t len, void *o)
70 | {
71 | const unsigned char *ib = i;
72 | unsigned char *ob = o;
73 | size_t n = 0;
74 |
75 | while (len--) {
76 | b->queue |= *ib++ << b->nbits;
77 | b->nbits += 8;
78 | if (b->nbits > 13) { /* enough bits in queue */
79 | unsigned int val = b->queue & 8191;
80 |
81 | if (val > 88) {
82 | b->queue >>= 13;
83 | b->nbits -= 13;
84 | } else { /* we can take 14 bits */
85 | val = b->queue & 16383;
86 | b->queue >>= 14;
87 | b->nbits -= 14;
88 | }
89 | ob[n++] = enctab[val % 91];
90 | ob[n++] = enctab[val / 91];
91 | }
92 | }
93 |
94 | return n;
95 | }
96 |
97 | /* process remaining bits from bit queue; write up to 2 bytes */
98 |
99 | size_t basE91_encode_end(struct basE91 *b, void *o)
100 | {
101 | unsigned char *ob = o;
102 | size_t n = 0;
103 |
104 | if (b->nbits) {
105 | ob[n++] = enctab[b->queue % 91];
106 | if (b->nbits > 7 || b->queue > 90)
107 | ob[n++] = enctab[b->queue / 91];
108 | }
109 | b->queue = 0;
110 | b->nbits = 0;
111 | b->val = -1;
112 |
113 | return n;
114 | }
115 |
116 | size_t basE91_decode(struct basE91 *b, const void *i, size_t len, void *o)
117 | {
118 | const unsigned char *ib = i;
119 | unsigned char *ob = o;
120 | size_t n = 0;
121 | unsigned int d;
122 |
123 | while (len--) {
124 | d = dectab[*ib++];
125 | if (d == 91)
126 | continue; /* ignore non-alphabet chars */
127 | if (b->val == -1)
128 | b->val = d; /* start next value */
129 | else {
130 | b->val += d * 91;
131 | b->queue |= b->val << b->nbits;
132 | b->nbits += (b->val & 8191) > 88 ? 13 : 14;
133 | do {
134 | ob[n++] = b->queue;
135 | b->queue >>= 8;
136 | b->nbits -= 8;
137 | } while (b->nbits > 7);
138 | b->val = -1; /* mark value complete */
139 | }
140 | }
141 |
142 | return n;
143 | }
144 |
145 | /* process remaining bits; write at most 1 byte */
146 |
147 | size_t basE91_decode_end(struct basE91 *b, void *o)
148 | {
149 | unsigned char *ob = o;
150 | size_t n = 0;
151 |
152 | if (b->val != -1)
153 | ob[n++] = b->queue | b->val << b->nbits;
154 | b->queue = 0;
155 | b->nbits = 0;
156 | b->val = -1;
157 |
158 | return n;
159 | }
160 |
--------------------------------------------------------------------------------
/encoders/base91.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2000-2006 Joachim Henke
3 | *
4 | * For conditions of distribution and use, see copyright notice in base91.c
5 | */
6 |
7 | #ifndef BASE91_H
8 | #define BASE91_H 1
9 |
10 | #include
11 |
12 | struct basE91 {
13 | unsigned long queue;
14 | unsigned int nbits;
15 | int val;
16 | };
17 |
18 | void basE91_init(struct basE91 *);
19 |
20 | size_t basE91_encode(struct basE91 *, const void *, size_t, void *);
21 |
22 | size_t basE91_encode_end(struct basE91 *, void *);
23 |
24 | size_t basE91_decode(struct basE91 *, const void *, size_t, void *);
25 |
26 | size_t basE91_decode_end(struct basE91 *, void *);
27 |
28 | #endif /* base91.h */
29 |
--------------------------------------------------------------------------------
/encoders/encoders.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "encoders.h"
4 |
5 | int base91_glue_encode(unsigned char const *src, size_t srclength,
6 | void *target, size_t targsize) {
7 | static struct basE91 b91;
8 | size_t s;
9 | int total_size = 0;
10 |
11 | // zero the output buffer
12 | memset(target,'\0',targsize);
13 |
14 | // setup the base91 struct
15 | basE91_init(&b91);
16 |
17 | // encode most of it and keep the size
18 | s = basE91_encode(&b91, src, srclength, target);
19 | total_size += s;
20 |
21 | // pickup anything left and keep the size
22 | s = basE91_encode_end(&b91, (void*)(target+s));
23 | total_size += s;
24 |
25 | // return the total size
26 | return total_size;
27 | }
--------------------------------------------------------------------------------
/encoders/encoders.h:
--------------------------------------------------------------------------------
1 | #ifndef _ENCODERS_H_
2 | #define _ENCODERS_H_
3 |
4 | #include "b10.h"
5 | #include "b64.h"
6 | #include "base91.h"
7 | #include "base16.h"
8 | #include "skey.h"
9 | #include "z85.h"
10 |
11 | /* encode stuff using basE91 internal functions */
12 | int base91_glue_encode(unsigned char const *src, size_t srclength,
13 | void *target, size_t targsize);
14 |
15 | #endif
--------------------------------------------------------------------------------
/encoders/skey.h:
--------------------------------------------------------------------------------
1 | int libscrypt_skey_encode(unsigned char const *src, size_t srclength,
2 | /*@out@*/ char *target, size_t targetsize);
3 |
--------------------------------------------------------------------------------
/encoders/z85.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Stanislav Artemkin .
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are
6 | * met:
7 | *
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above
11 | * copyright notice, this list of conditions and the following disclaimer
12 | * in the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | *
27 | * Implementation of 32/Z85 specification (http://rfc.zeromq.org/spec:32/Z85)
28 | * Source repository: http://github.com/artemkin/z85
29 | */
30 |
31 | #include
32 | #include
33 | #include
34 |
35 | #include "z85.h"
36 |
37 | typedef unsigned int uint32_t;
38 | typedef unsigned char byte;
39 |
40 | // make sure uint32_t is 32-bit
41 | typedef char Z85_uint32_t_static_assert[(sizeof(uint32_t) * CHAR_BIT == 32) * 2 - 1];
42 |
43 | #define DIV85_MAGIC 3233857729ULL
44 | // make sure magic constant is 64-bit
45 | typedef char Z85_div85_magic_static_assert[(sizeof(DIV85_MAGIC) * CHAR_BIT == 64) * 2 - 1];
46 |
47 | #define DIV85(number) ((uint32_t)((DIV85_MAGIC * number) >> 32) >> 6)
48 |
49 | static const char* base85 =
50 | {
51 | "0123456789"
52 | "abcdefghij"
53 | "klmnopqrst"
54 | "uvwxyzABCD"
55 | "EFGHIJKLMN"
56 | "OPQRSTUVWX"
57 | "YZ.-:+=^!/"
58 | "*?&<>()[]{"
59 | "}@%$#"
60 | };
61 |
62 | static byte base256[] =
63 | {
64 | 0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00,
65 | 0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45,
66 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
67 | 0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47,
68 | 0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
69 | 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
70 | 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
71 | 0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00,
72 | 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
73 | 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
74 | 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
75 | 0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00
76 | };
77 |
78 | int libscrypt_z85_encode(src, srclength, target, targsize)
79 | unsigned char const *src;
80 | size_t srclength;
81 | char *target;
82 | size_t targsize;
83 | {
84 | size_t datalength = 0;
85 | memset(target, 0, targsize);
86 |
87 | if (targsize < (Z85_encode_with_padding_bound(srclength) + 1)) {
88 | return (-1); //not enough space for output
89 | }
90 |
91 | //encode the input buffer, padding it if necessary
92 | datalength = Z85_encode_with_padding((const char * )src, target, srclength);
93 | if ( datalength == 0)
94 | return (-1); //something went wrong
95 |
96 | target[datalength] = '\0'; // write null terminating char
97 | return datalength;
98 | }
99 |
100 | int libscrypt_z85_decode(src, target, targsize)
101 | char const *src;
102 | unsigned char *target;
103 | size_t targsize;
104 | {
105 | size_t datalength = 0;
106 | if (targsize < (Z85_decode_with_padding_bound(src, strlen(src)) + 1)) {
107 | return (-1); //not enough space for output
108 | }
109 |
110 | //decode the input buffer, padding it if necessary
111 | datalength = Z85_decode_with_padding(src, (char *) target, strlen(src));
112 | if ( datalength == 0)
113 | return (-1); //something went wrong
114 |
115 | target[datalength] = '\0'; // write null terminating char
116 | return datalength;
117 | }
118 |
119 | char* Z85_encode_unsafe(const char* source, const char* sourceEnd, char* dest)
120 | {
121 | byte* src = (byte*)source;
122 | byte* end = (byte*)sourceEnd;
123 | byte* dst = (byte*)dest;
124 | uint32_t value;
125 | uint32_t value2;
126 |
127 | for (; src != end; src += 4, dst += 5)
128 | {
129 | // unpack big-endian frame
130 | value = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
131 |
132 | value2 = DIV85(value); dst[4] = base85[value - value2 * 85]; value = value2;
133 | value2 = DIV85(value); dst[3] = base85[value - value2 * 85]; value = value2;
134 | value2 = DIV85(value); dst[2] = base85[value - value2 * 85]; value = value2;
135 | value2 = DIV85(value); dst[1] = base85[value - value2 * 85];
136 | dst[0] = base85[value2];
137 | }
138 |
139 | return (char*)dst;
140 | }
141 |
142 | char* Z85_decode_unsafe(const char* source, const char* sourceEnd, char* dest)
143 | {
144 | byte* src = (byte*)source;
145 | byte* end = (byte*)sourceEnd;
146 | byte* dst = (byte*)dest;
147 | uint32_t value;
148 |
149 | for (; src != end; src += 5, dst += 4)
150 | {
151 | value = base256[(src[0] - 32) & 127];
152 | value = value * 85 + base256[(src[1] - 32) & 127];
153 | value = value * 85 + base256[(src[2] - 32) & 127];
154 | value = value * 85 + base256[(src[3] - 32) & 127];
155 | value = value * 85 + base256[(src[4] - 32) & 127];
156 |
157 | // pack big-endian frame
158 | dst[0] = value >> 24;
159 | dst[1] = (byte)(value >> 16);
160 | dst[2] = (byte)(value >> 8);
161 | dst[3] = (byte)(value);
162 | }
163 |
164 | return (char*)dst;
165 | }
166 |
167 | size_t Z85_encode_bound(size_t size)
168 | {
169 | return size * 5 / 4;
170 | }
171 |
172 | size_t Z85_decode_bound(size_t size)
173 | {
174 | return size * 4 / 5;
175 | }
176 |
177 | size_t Z85_encode(const char* source, char* dest, size_t inputSize)
178 | {
179 | if (!source || !dest || inputSize % 4)
180 | {
181 | assert(!"wrong source, destination or input size");
182 | return 0;
183 | }
184 |
185 | return Z85_encode_unsafe(source, source + inputSize, dest) - dest;
186 | }
187 |
188 | size_t Z85_decode(const char* source, char* dest, size_t inputSize)
189 | {
190 | if (!source || !dest || inputSize % 5)
191 | {
192 | assert(!"wrong source, destination or input size");
193 | return 0;
194 | }
195 |
196 | return Z85_decode_unsafe(source, source + inputSize, dest) - dest;
197 | }
198 |
199 | size_t Z85_encode_with_padding_bound(size_t size)
200 | {
201 | if (size == 0) return 0;
202 | size = Z85_encode_bound(size);
203 | return size + (5 - size % 5) % 5 + 1;
204 | }
205 |
206 | size_t Z85_decode_with_padding_bound(const char* source, size_t size)
207 | {
208 | if (size == 0 || !source || (byte)(source[0] - '0' - 1) > 3) return 0;
209 | return Z85_decode_bound(size - 1) - 4 + (source[0] - '0');
210 | }
211 |
212 | size_t Z85_encode_with_padding(const char* source, char* dest, size_t inputSize)
213 | {
214 | size_t tailBytes = inputSize % 4;
215 | char tailBuf[4] = { 0 };
216 | char* dst = dest;
217 | const char* end = source + inputSize - tailBytes;
218 |
219 | assert(source && dest);
220 |
221 | // zero length string is not padded
222 | if (!source || !dest || inputSize == 0)
223 | {
224 | return 0;
225 | }
226 |
227 | (dst++)[0] = (tailBytes == 0 ? '4' : '0' + (char)tailBytes); // write tail bytes count
228 | dst = Z85_encode_unsafe(source, end, dst); // write body
229 |
230 | // write tail
231 | switch (tailBytes)
232 | {
233 | case 3:
234 | tailBuf[2] = end[2];
235 | case 2:
236 | tailBuf[1] = end[1];
237 | case 1:
238 | tailBuf[0] = end[0];
239 | dst = Z85_encode_unsafe(tailBuf, tailBuf + 4, dst);
240 | }
241 |
242 | return dst - dest;
243 | }
244 |
245 | size_t Z85_decode_with_padding(const char* source, char* dest, size_t inputSize)
246 | {
247 | char* dst = dest;
248 | size_t tailBytes;
249 | char tailBuf[4] = { 0 };
250 | const char* end = source + inputSize;
251 |
252 | assert(source && dest && (inputSize == 0 || (inputSize - 1) % 5 == 0));
253 |
254 | // zero length string is not padded
255 | if (!source || !dest || inputSize == 0 || (inputSize - 1) % 5)
256 | {
257 | return 0;
258 | }
259 |
260 | tailBytes = (source++)[0] - '0'; // possible values: 1, 2, 3 or 4
261 | if (tailBytes - 1 > 3)
262 | {
263 | assert(!"wrong tail bytes count");
264 | return 0;
265 | }
266 |
267 | end -= 5;
268 | if (source != end)
269 | {
270 | // decode body
271 | dst = Z85_decode_unsafe(source, end, dst);
272 | }
273 |
274 | // decode last 5 bytes chunk
275 | Z85_decode_unsafe(end, end + 5, tailBuf);
276 |
277 | switch (tailBytes)
278 | {
279 | case 4:
280 | dst[3] = tailBuf[3];
281 | case 3:
282 | dst[2] = tailBuf[2];
283 | case 2:
284 | dst[1] = tailBuf[1];
285 | case 1:
286 | dst[0] = tailBuf[0];
287 | }
288 |
289 | return dst - dest + tailBytes;
290 | }
291 |
--------------------------------------------------------------------------------
/encoders/z85.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Stanislav Artemkin .
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are
6 | * met:
7 | *
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above
11 | * copyright notice, this list of conditions and the following disclaimer
12 | * in the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | *
27 | * Implementation of 32/Z85 specification (http://rfc.zeromq.org/spec:32/Z85)
28 | * Source repository: http://github.com/artemkin/z85
29 | */
30 |
31 | #pragma once
32 |
33 | #include
34 |
35 | #if defined (__cplusplus)
36 | extern "C" {
37 | #endif
38 |
39 | /*******************************************************************************
40 | * libscrypt wrappers *
41 | *******************************************************************************/
42 | int libscrypt_z85_encode(unsigned char const *src, size_t srclength,
43 | /*@out@*/ char *target, size_t targetsize);
44 | int libscrypt_z85_decode(char const *src,
45 | /*@out@*/ unsigned char *target, size_t targetsize);
46 |
47 | /*******************************************************************************
48 | * ZeroMQ Base-85 encoding/decoding functions with custom padding *
49 | *******************************************************************************/
50 |
51 | /**
52 | * @brief Encodes 'inputSize' bytes from 'source' into 'dest'.
53 | * If 'inputSize' is not divisible by 4 with no remainder, 'source' is padded.
54 | * Destination buffer must be already allocated. Use Z85_encode_with_padding_bound() to
55 | * evaluate size of the destination buffer.
56 | *
57 | * @param source in, input buffer (binary string to be encoded)
58 | * @param dest out, destination buffer
59 | * @param inputSize in, number of bytes to be encoded
60 | * @return number of printable symbols written into 'dest' or 0 if something goes wrong
61 | */
62 | size_t Z85_encode_with_padding(const char* source, char* dest, size_t inputSize);
63 |
64 | /**
65 | * @brief Decodes 'inputSize' printable symbols from 'source' into 'dest',
66 | * encoded with Z85_encode_with_padding().
67 | * Destination buffer must be already allocated. Use Z85_decode_with_padding_bound() to
68 | * evaluate size of the destination buffer.
69 | *
70 | * @param source in, input buffer (printable string to be decoded)
71 | * @param dest out, destination buffer
72 | * @param inputSize in, number of symbols to be decoded
73 | * @return number of bytes written into 'dest' or 0 if something goes wrong
74 | */
75 | size_t Z85_decode_with_padding(const char* source, char* dest, size_t inputSize);
76 |
77 | /**
78 | * @brief Evaluates a size of output buffer needed to encode 'size' bytes
79 | * into string of printable symbols using Z85_encode_with_padding().
80 | *
81 | * @param size in, number of bytes to be encoded
82 | * @return minimal size of output buffer in bytes
83 | */
84 | size_t Z85_encode_with_padding_bound(size_t size);
85 |
86 | /**
87 | * @brief Evaluates a size of output buffer needed to decode 'size' symbols
88 | * into binary string using Z85_decode_with_padding().
89 | *
90 | * @param source in, input buffer (first symbol is read from 'source' to evaluate padding)
91 | * @param size in, number of symbols to be decoded
92 | * @return minimal size of output buffer in bytes
93 | */
94 | size_t Z85_decode_with_padding_bound(const char* source, size_t size);
95 |
96 |
97 |
98 | /*******************************************************************************
99 | * ZeroMQ Base-85 encoding/decoding functions (specification compliant) *
100 | *******************************************************************************/
101 |
102 | /**
103 | * @brief Encodes 'inputSize' bytes from 'source' into 'dest'.
104 | * If 'inputSize' is not divisible by 4 with no remainder, 0 is retured.
105 | * Destination buffer must be already allocated. Use Z85_encode_bound() to
106 | * evaluate size of the destination buffer.
107 | *
108 | * @param source in, input buffer (binary string to be encoded)
109 | * @param dest out, destination buffer
110 | * @param inputSize in, number of bytes to be encoded
111 | * @return number of printable symbols written into 'dest' or 0 if something goes wrong
112 | */
113 | size_t Z85_encode(const char* source, char* dest, size_t inputSize);
114 |
115 | /**
116 | * @brief Decodes 'inputSize' printable symbols from 'source' into 'dest'.
117 | * If 'inputSize' is not divisible by 5 with no remainder, 0 is returned.
118 | * Destination buffer must be already allocated. Use Z85_decode_bound() to
119 | * evaluate size of the destination buffer.
120 | *
121 | * @param source in, input buffer (printable string to be decoded)
122 | * @param dest out, destination buffer
123 | * @param inputSize in, number of symbols to be decoded
124 | * @return number of bytes written into 'dest' or 0 if something goes wrong
125 | */
126 | size_t Z85_decode(const char* source, char* dest, size_t inputSize);
127 |
128 | /**
129 | * @brief Evaluates a size of output buffer needed to encode 'size' bytes
130 | * into string of printable symbols using Z85_encode().
131 | *
132 | * @param size in, number of bytes to be encoded
133 | * @return minimal size of output buffer in bytes
134 | */
135 | size_t Z85_encode_bound(size_t size);
136 |
137 | /**
138 | * @brief Evaluates a size of output buffer needed to decode 'size' symbols
139 | * into binary string using Z85_decode().
140 | *
141 | * @param size in, number of symbols to be decoded
142 | * @return minimal size of output buffer in bytes
143 | */
144 | size_t Z85_decode_bound(size_t size);
145 |
146 |
147 |
148 | /*******************************************************************************
149 | * ZeroMQ Base-85 unsafe encoding/decoding functions (specification compliant) *
150 | *******************************************************************************/
151 |
152 | /**
153 | * @brief Encodes bytes from [source;sourceEnd) range into 'dest'.
154 | * It can be used for implementation of your own padding scheme.
155 | * Preconditions:
156 | * - (sourceEnd - source) % 4 == 0
157 | * - destination buffer must be already allocated
158 | *
159 | * @param source in, begin of input buffer
160 | * @param sourceEnd in, end of input buffer (not included)
161 | * @param dest out, output buffer
162 | * @return a pointer immediately after last symbol written into the 'dest'
163 | */
164 | char* Z85_encode_unsafe(const char* source, const char* sourceEnd, char* dest);
165 |
166 | /**
167 | * @brief Decodes symbols from [source;sourceEnd) range into 'dest'.
168 | * It can be used for implementation of your own padding scheme.
169 | * Preconditions:
170 | * - (sourceEnd - source) % 5 == 0
171 | * - destination buffer must be already allocated
172 | *
173 | * @param source in, begin of input buffer
174 | * @param sourceEnd in, end of input buffer (not included)
175 | * @param dest out, output buffer
176 | * @return a pointer immediately after last byte written into the 'dest'
177 | */
178 | char* Z85_decode_unsafe(const char* source, const char* sourceEnd, char* dest);
179 |
180 | #if defined (__cplusplus)
181 | }
182 | #endif
183 |
184 |
--------------------------------------------------------------------------------
/genpass.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/javier-lopez/genpass/955b1d578e17632579d6c75b2b6a2417a0b51c41/genpass.gif
--------------------------------------------------------------------------------
/libscrypt/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013, Joshua Small
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6 | 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.
7 |
8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
9 |
10 |
--------------------------------------------------------------------------------
/libscrypt/Makefile:
--------------------------------------------------------------------------------
1 | PREFIX ?= /usr/local
2 | LIBDIR ?= $(PREFIX)/lib
3 | INCLUDEDIR ?= $(PREFIX)/include
4 | MAKE_DIR ?= install -d
5 | INSTALL_DATA ?= install
6 |
7 | CC?=gcc
8 | CFLAGS=-O2 -Wall -g -D_FORTIFY_SOURCE=2 -fstack-protector -fPIC
9 | LDFLAGS=-Wl,-z,now -Wl,-z,relro -Wl,-soname,libscrypt.so.0 -Wl,--version-script=libscrypt.version
10 | CFLAGS_EXTRA=-Wl,-rpath=.
11 |
12 | all: reference
13 |
14 | OBJS= crypto_scrypt-nosse.o sha256.o crypto-mcf.o b64.o z85.o b10.o skey.o crypto-scrypt-saltgen.o crypto_scrypt-check.o crypto_scrypt-hash.o slowequals.o
15 |
16 | libscrypt.so.0: $(OBJS)
17 | $(CC) $(LDFLAGS) -shared -o libscrypt.so.0 $(OBJS) -lm -lc
18 | ar rcs libscrypt.a $(OBJS)
19 |
20 | reference: libscrypt.so.0 main.o crypto_scrypt-hexconvert.o
21 | ln -s -f libscrypt.so.0 libscrypt.so
22 | $(CC) -Wall -o reference main.o b64.o z85.o b10.o skey.o crypto_scrypt-hexconvert.o $(CFLAGS_EXTRA) -L. -lscrypt
23 | $(CC) -Wall -static -o reference-static main.o b64.o z85.o b10.o skey.o crypto_scrypt-hexconvert.o $(CFLAGS_EXTRA) -L. -lscrypt
24 |
25 | clean:
26 | rm -f *.o reference* libscrypt.so* libscrypt.a endian.h
27 |
28 | check: all
29 | ./reference
30 |
31 | devtest:
32 | splint crypto_scrypt-hexconvert.c
33 | splint crypto-mcf.c crypto_scrypt-check.c crypto_scrypt-hash.c -unrecog
34 | splint crypto-scrypt-saltgen.c +posixlib -compdef
35 | valgrind ./reference
36 |
37 | asan: main.c
38 | clang -O1 -g -fsanitize=address -fno-omit-frame-pointer *.c -o asantest
39 | ./asantest
40 | scan-build clang -O1 -g -fsanitize=undefined -fno-omit-frame-pointer *.c -o asantest
41 | ./asantest
42 | rm -f asantest
43 |
44 | install: libscrypt.so.0
45 | $(MAKE_DIR) $(DESTDIR) $(DESTDIR)$(PREFIX) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR)
46 | $(INSTALL_DATA) -pm 0755 libscrypt.so.0 $(DESTDIR)$(LIBDIR)
47 | cd $(DESTDIR)$(LIBDIR) && ln -s -f libscrypt.so.0 $(DESTDIR)$(LIBDIR)/libscrypt.so
48 | $(INSTALL_DATA) -pm 0644 libscrypt.h $(DESTDIR)$(INCLUDEDIR)
49 |
50 | install-osx: libscrypt.so.0
51 | $(MAKE_DIR) $(DESTDIR) $(DESTDIR)$(PREFIX) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR)
52 | $(INSTALL_DATA) -pm 0755 libscrypt.so.0 $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib
53 | cd $(DESTDIR)$(LIBDIR) && install_name_tool -id $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib
54 | cd $(DESTDIR)$(LIBDIR) && ln -s -f libscrypt.0.dylib $(DESTDIR)$(LIBDIR)/libscrypt.dylib
55 | $(INSTALL_DATA) -pm 0644 libscrypt.h $(DESTDIR)$(INCLUDEDIR)
56 |
57 | install-static: libscrypt.a
58 | $(INSTALL_DATA) -pm 0644 libscrypt.a $(DESTDIR)$(LIBDIR)
59 |
--------------------------------------------------------------------------------
/libscrypt/README.md:
--------------------------------------------------------------------------------
1 | libscrypt
2 | =========
3 | Linux scrypt shared library.
4 |
5 | Full credit to algorithm designer and example code from Colin Percival here:
6 | http://www.tarsnap.com/scrypt.html
7 |
8 | Utilises BASE64 encoding library from ISC.
9 |
10 | Official project page, including stable tarballs found here:
11 | http://www.lolware.net/libscrypt.html
12 |
13 | Simple hashing interface
14 |
15 | The (reference) internal hashing function can be directly called as follows:
16 |
17 | int libscrypt_scrypt(const uint8_t *passwd, size_t passwdlen,
18 | const uint8_t *salt, size_t saltlen, uint64_t N, uint32_t r,
19 | uint32_t p, /*@out@*/ uint8_t *buf, size_t buflen);
20 |
21 | Libscrypt's easier to use interface wraps this up to deal with the salt and produce BASE64 output as so:
22 |
23 | int libscrypt_hash(char *dst, char *passphrase, uint32_t N, uint8_t r, uint8_t p);
24 |
25 | Sane constants have been created for N, r and p so you can create a hash like this:
26 |
27 | libscrypt_hash(outbuf, "My cats's breath smells like cat food", SCRYPT_N, SCRYPT_r, SCRYPT_p);
28 |
29 | This function sets errno as required for any error conditions.
30 |
31 | Output stored in "outbuf" is stored in a standardised MCF form, which means includes the randomly created, 128 bit salt, all N, r and p values, and a BASE64 encoded version of the hash. The entire MCF can be stored in a database, and compared for use as below:
32 |
33 | retval = libscrypt_check(mcf, "pleasefailme");
34 | retval < 0 error
35 | retval = 0 password incorrect
36 | retval > 0 pass
37 |
38 | mcf should be defined as at least SCRYPT_MCF_LEN in size.
39 |
40 | Note that libscrypt_check needs to modify the mcf string and will not return it
41 | to the original state. Pass it a copy if you need to keep the original mcf.
42 |
43 | A number of internal functions are exposed, and users wishing to create more complex use cases should consult the header file, which is aimed at documenting the API fully.
44 |
45 | The test reference is also aimed at providing a well documented use case.
46 | Building
47 | --------
48 | make
49 | make check
50 | Check the Makefile for advice on linking against your application.
51 |
52 | OSX
53 | -----
54 | Please compile and install with:
55 |
56 | make LDFLAGS= CFLAGS_EXTRA=
57 | make install-osx
58 |
59 |
60 | BUGS
61 | ----
62 | SCRYPT_* constants are probably a little high for something like a Raspberry pi. Using '1' as SCRYPT_p is acceptable from a security and performance standpoint if needed.
63 | Experiments were performed with using memset() to zero out passwords as they were checked. This often caused issues with calling applications where the password based have been passed as a const*. We highly recommend implementing your own zeroing function the moment this library is called.
64 |
65 | There is apparently an issue when used on Samsung (and perhaps Android in general) devices. See [this issue](https://github.com/technion/libscrypt/issues/39) for more information.
66 |
67 | Notes on Code Development
68 | ------------------------
69 |
70 | Code is now declared "stable", the master branch will always be "stable" and development will be done on branches.
71 | The reference machines are Fedora, CentOS, FreeBSD and Raspbian, and the code is expected to compile and run on all of these before being moved to stable branch.
72 | Full transparancy on the regular application of thorough testing can be found by reviewing recent test harness results here:
73 | http://www.lolware.net/libscrypttesting.txt
74 |
75 | Please, no more pull requests for Windows compatibility. If it's important to you - fork the project. I have no intention of pulling an OpenSSL and becoming a maze of ifdefs for platforms I don't even have a build environment for.
76 |
77 | I utilise Facebook's "infer" static analyser, in addition to clang's analyzer. Command to run is:
78 |
79 | infer -- make
80 |
81 | Contact
82 | -------
83 | I can be contacted at: technion@lolware.net
84 |
85 | If required, my GPG key can be found at: https://lolware.net/technion-GPG-KEY
86 |
87 | Future releases will have the Git tag signed.
88 |
89 |
90 | Changenotes
91 | -----------
92 | v1.1a: Single Makefile line change. I wouldn't ordinarily tag this as a new "release", but the purpose here is to assist with packaging in distributions.
93 |
94 | v1.12: The static library is built, but no longer installed by default. You can install it with "make install-static". This is because static libraries are not typically bundled in packages.
95 |
96 | v1.13: Minor packaging related update
97 |
98 | v1.15: Replaced the b64 libraries with more portable one from ISC. Now tested and verified on a wider variety of architectures. Note, libscrypt_b64_encrypt was originally an exported function. This is no longer the case as it is considered an internal function only.
99 |
100 | v1.18: God damnit Apple
101 |
102 | v1.19: Code safety cleanups. Now running Coverity.
103 |
104 | v1.20: Bigfixes involving large N values, return values on error
105 |
106 |
107 |
109 |
110 |
--------------------------------------------------------------------------------
/libscrypt/b10.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "crypto_scrypt-hexconvert.h"
9 |
10 | int libscrypt_b10_encode(src, srclength, target, targsize)
11 | unsigned char const *src;
12 | size_t srclength;
13 | char *target;
14 | size_t targsize;
15 | {
16 | size_t i;
17 | int len = 0;
18 |
19 | if (!src || srclength < 1 || targsize < (srclength * 2 + 1))
20 | return -1;
21 |
22 | memset(target, 0, targsize);
23 |
24 | for(i=0; i<=(srclength-1); i++)
25 | {
26 | /* snprintf(target, srclength,"%s...", target....) has undefined results
27 | * and can't be used. Using offests like this makes snprintf
28 | * nontrivial. we therefore have use inescure sprintf() and
29 | * lengths checked elsewhere (start of function) */
30 | /*@ -bufferoverflowhigh @*/
31 | len += sprintf(target+len, "%02u", (unsigned int) src[i]);
32 | }
33 |
34 | return 0;
35 |
36 | /*if (libscrypt_hex_encode(src, srclength, target, targsize) == -1) return -1;*/
37 | /*char *p;*/
38 | /*errno = 0;*/
39 | /*unsigned long int b10 = strtoul(target,&p,16);*/
40 |
41 | /*if (p == target) //no digits found*/
42 | /*return -1;*/
43 | /*else if ((b10 == LONG_MIN || b10 == ULONG_MAX) && errno == ERANGE)*/
44 | /*//value out of range*/
45 | /*return -1;*/
46 | /*else*/
47 | /*snprintf(target, targsize, "%ld", b10);*/
48 |
49 | /*return 0;*/
50 | }
51 |
--------------------------------------------------------------------------------
/libscrypt/b10.h:
--------------------------------------------------------------------------------
1 | int libscrypt_b10_encode(unsigned char const *src, size_t srclength,
2 | /*@out@*/ char *target, size_t targetsize);
3 |
--------------------------------------------------------------------------------
/libscrypt/b64.c:
--------------------------------------------------------------------------------
1 | /*Base64 encode/decode functions from OpenBSD (src/lib/libc/net/base64.c).*/
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "b64.h"
10 |
11 | static const char Base64Compliant[] =
12 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
13 | static const char Pad64Compliant = '=';
14 |
15 | static const char Base64[] =
16 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_";
17 | static const char Pad64 = '\0';
18 |
19 | /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
20 | The following encoding technique is taken from RFC 1521 by Borenstein
21 | and Freed. It is reproduced here in a slightly edited form for
22 | convenience.
23 |
24 | A 65-character subset of US-ASCII is used, enabling 6 bits to be
25 | represented per printable character. (The extra 65th character, "=",
26 | is used to signify a special processing function.)
27 |
28 | The encoding process represents 24-bit groups of input bits as output
29 | strings of 4 encoded characters. Proceeding from left to right, a
30 | 24-bit input group is formed by concatenating 3 8-bit input groups.
31 | These 24 bits are then treated as 4 concatenated 6-bit groups, each
32 | of which is translated into a single digit in the base64 alphabet.
33 |
34 | Each 6-bit group is used as an index into an array of 64 printable
35 | characters. The character referenced by the index is placed in the
36 | output string.
37 |
38 | Table 1: The Base64 Alphabet
39 |
40 | Value Encoding Value Encoding Value Encoding Value Encoding
41 | 0 A 17 R 34 i 51 z
42 | 1 B 18 S 35 j 52 0
43 | 2 C 19 T 36 k 53 1
44 | 3 D 20 U 37 l 54 2
45 | 4 E 21 V 38 m 55 3
46 | 5 F 22 W 39 n 56 4
47 | 6 G 23 X 40 o 57 5
48 | 7 H 24 Y 41 p 58 6
49 | 8 I 25 Z 42 q 59 7
50 | 9 J 26 a 43 r 60 8
51 | 10 K 27 b 44 s 61 9
52 | 11 L 28 c 45 t 62 +
53 | 12 M 29 d 46 u 63 /
54 | 13 N 30 e 47 v
55 | 14 O 31 f 48 w (pad) =
56 | 15 P 32 g 49 x
57 | 16 Q 33 h 50 y
58 |
59 | Special processing is performed if fewer than 24 bits are available
60 | at the end of the data being encoded. A full encoding quantum is
61 | always completed at the end of a quantity. When fewer than 24 input
62 | bits are available in an input group, zero bits are added (on the
63 | right) to form an integral number of 6-bit groups. Padding at the
64 | end of the data is performed using the '=' character.
65 |
66 | Since all base64 input is an integral number of octets, only the
67 | -------------------------------------------------
68 | following cases can arise:
69 |
70 | (1) the final quantum of encoding input is an integral
71 | multiple of 24 bits; here, the final unit of encoded
72 | output will be an integral multiple of 4 characters
73 | with no "=" padding,
74 | (2) the final quantum of encoding input is exactly 8 bits;
75 | here, the final unit of encoded output will be two
76 | characters followed by two "=" padding characters, or
77 | (3) the final quantum of encoding input is exactly 16 bits;
78 | here, the final unit of encoded output will be three
79 | characters followed by one "=" padding character.
80 | */
81 |
82 | int
83 | libscrypt_b64_encode(src, srclength, target, targsize)
84 | unsigned char const *src;
85 | size_t srclength;
86 | char *target;
87 | size_t targsize;
88 | {
89 | size_t datalength = 0;
90 | unsigned char input[3];
91 | unsigned char output[4];
92 | unsigned int i;
93 |
94 | memset(target, 0, targsize);
95 |
96 | while (2 < srclength) {
97 | input[0] = *src++;
98 | input[1] = *src++;
99 | input[2] = *src++;
100 | srclength -= 3;
101 |
102 | output[0] = input[0] >> 2;
103 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
104 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
105 | output[3] = input[2] & 0x3f;
106 |
107 | if (datalength + 4 > targsize)
108 | return (-1);
109 | target[datalength++] = Base64[output[0]];
110 | target[datalength++] = Base64[output[1]];
111 | target[datalength++] = Base64[output[2]];
112 | target[datalength++] = Base64[output[3]];
113 | }
114 |
115 | /* Now we worry about padding. */
116 | if (0 != srclength) {
117 | /* Get what's left. */
118 | input[0] = input[1] = input[2] = '\0';
119 | for (i = 0; i < srclength; i++)
120 | input[i] = *src++;
121 |
122 | output[0] = input[0] >> 2;
123 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
124 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
125 |
126 | if (datalength + 4 > targsize)
127 | return (-1);
128 | target[datalength++] = Base64[output[0]];
129 | target[datalength++] = Base64[output[1]];
130 | if (srclength == 1)
131 | target[datalength++] = Pad64;
132 | else
133 | target[datalength++] = Base64[output[2]];
134 | target[datalength++] = Pad64;
135 | }
136 | if (datalength >= targsize)
137 | return (-1);
138 | target[datalength] = '\0'; /* Returned value doesn't count \0. */
139 | return (int)(datalength);
140 | }
141 |
142 | int
143 | libscrypt_b64_encode_compliant(src, srclength, target, targsize)
144 | unsigned char const *src;
145 | size_t srclength;
146 | char *target;
147 | size_t targsize;
148 | {
149 | size_t datalength = 0;
150 | unsigned char input[3];
151 | unsigned char output[4];
152 | unsigned int i;
153 |
154 | memset(target, 0, targsize);
155 |
156 | while (2 < srclength) {
157 | input[0] = *src++;
158 | input[1] = *src++;
159 | input[2] = *src++;
160 | srclength -= 3;
161 |
162 | output[0] = input[0] >> 2;
163 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
164 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
165 | output[3] = input[2] & 0x3f;
166 |
167 | if (datalength + 4 > targsize)
168 | return (-1);
169 | target[datalength++] = Base64Compliant[output[0]];
170 | target[datalength++] = Base64Compliant[output[1]];
171 | target[datalength++] = Base64Compliant[output[2]];
172 | target[datalength++] = Base64Compliant[output[3]];
173 | }
174 |
175 | /* Now we worry about padding. */
176 | if (0 != srclength) {
177 | /* Get what's left. */
178 | input[0] = input[1] = input[2] = '\0';
179 | for (i = 0; i < srclength; i++)
180 | input[i] = *src++;
181 |
182 | output[0] = input[0] >> 2;
183 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
184 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
185 |
186 | if (datalength + 4 > targsize)
187 | return (-1);
188 | target[datalength++] = Base64Compliant[output[0]];
189 | target[datalength++] = Base64Compliant[output[1]];
190 | if (srclength == 1)
191 | target[datalength++] = Pad64Compliant;
192 | else
193 | target[datalength++] = Base64Compliant[output[2]];
194 | target[datalength++] = Pad64Compliant;
195 | }
196 | if (datalength >= targsize)
197 | return (-1);
198 | target[datalength] = '\0'; /* Returned value doesn't count \0. */
199 | return (int)(datalength);
200 | }
201 |
202 | /* skips all whitespace anywhere.
203 | converts characters, four at a time, starting at (or after)
204 | src from base - 64 numbers into three 8 bit bytes in the target area.
205 | it returns the number of data bytes stored at the target, or -1 on error.
206 | */
207 |
208 | int
209 | libscrypt_b64_decode_compliant(src, target, targsize)
210 | char const *src;
211 | unsigned char *target;
212 | size_t targsize;
213 | {
214 | int state, ch;
215 | unsigned int tarindex;
216 | unsigned char nextbyte;
217 | char *pos;
218 |
219 | state = 0;
220 | tarindex = 0;
221 |
222 | while ((ch = (unsigned char)*src++) != '\0') {
223 | if (isspace(ch)) /* Skip whitespace anywhere. */
224 | continue;
225 |
226 | if (ch == Pad64Compliant)
227 | break;
228 |
229 | pos = strchr(Base64Compliant, ch);
230 | if (pos == 0) /* A non-base64 character. */
231 | return (-1);
232 |
233 | switch (state) {
234 | case 0:
235 | if (target) {
236 | if (tarindex >= targsize)
237 | return (-1);
238 | target[tarindex] = (pos - Base64Compliant) << 2;
239 | }
240 | state = 1;
241 | break;
242 | case 1:
243 | if (target) {
244 | if (tarindex >= targsize)
245 | return (-1);
246 | target[tarindex] |= (pos - Base64Compliant) >> 4;
247 | nextbyte = ((pos - Base64Compliant) & 0x0f) << 4;
248 | if (tarindex + 1 < targsize)
249 | target[tarindex+1] = nextbyte;
250 | else if (nextbyte)
251 | return (-1);
252 | }
253 | tarindex++;
254 | state = 2;
255 | break;
256 | case 2:
257 | if (target) {
258 | if (tarindex >= targsize)
259 | return (-1);
260 | target[tarindex] |= (pos - Base64Compliant) >> 2;
261 | nextbyte = ((pos - Base64Compliant) & 0x03) << 6;
262 | if (tarindex + 1 < targsize)
263 | target[tarindex+1] = nextbyte;
264 | else if (nextbyte)
265 | return (-1);
266 | }
267 | tarindex++;
268 | state = 3;
269 | break;
270 | case 3:
271 | if (target) {
272 | if (tarindex >= targsize)
273 | return (-1);
274 | target[tarindex] |= (pos - Base64Compliant);
275 | }
276 | tarindex++;
277 | state = 0;
278 | break;
279 | }
280 | }
281 |
282 | /*
283 | * We are done decoding Base-64 chars. Let's see if we ended
284 | * on a byte boundary, and/or with erroneous trailing characters.
285 | */
286 |
287 | if (ch == Pad64Compliant) { /* We got a pad char. */
288 | ch = (unsigned char)*src++; /* Skip it, get next. */
289 | switch (state) {
290 | case 0: /* Invalid = in first position */
291 | case 1: /* Invalid = in second position */
292 | return (-1);
293 |
294 | case 2: /* Valid, means one byte of info */
295 | /* Skip any number of spaces. */
296 | for (; ch != '\0'; ch = (unsigned char)*src++)
297 | if (!isspace(ch))
298 | break;
299 | /* Make sure there is another trailing = sign. */
300 | if (ch != Pad64Compliant)
301 | return (-1);
302 | ch = (unsigned char)*src++; /* Skip the = */
303 | /* Fall through to "single trailing =" case. */
304 | /* FALLTHROUGH */
305 |
306 | case 3: /* Valid, means two bytes of info */
307 | /*
308 | * We know this char is an =. Is there anything but
309 | * whitespace after it?
310 | */
311 | for (; ch != '\0'; ch = (unsigned char)*src++)
312 | if (!isspace(ch))
313 | return (-1);
314 |
315 | /*
316 | * Now make sure for cases 2 and 3 that the "extra"
317 | * bits that slopped past the last full byte were
318 | * zeros. If we don't check them, they become a
319 | * subliminal channel.
320 | */
321 | if (target && tarindex < targsize &&
322 | target[tarindex] != 0)
323 | return (-1);
324 | }
325 | } else {
326 | /*
327 | * We ended by seeing the end of the string. Make sure we
328 | * have no partial bytes lying around.
329 | */
330 | if (state != 0)
331 | return (-1);
332 | }
333 |
334 | return (tarindex);
335 | }
336 |
--------------------------------------------------------------------------------
/libscrypt/b64.h:
--------------------------------------------------------------------------------
1 | /* BASE64 libraries used internally - should not need to be packaged */
2 | #include
3 | #define b64_encode_len(A) ((A+2)/3 * 4 + 1)
4 | #define b64_decode_len(A) (A / 4 * 3 + 2)
5 |
6 | //modified version, $_ instead of +/ and without '=' padding, optimized
7 | //for generating passwords
8 | int libscrypt_b64_encode(unsigned char const *src, size_t srclength,
9 | /*@out@*/ char *target, size_t targetsize);
10 |
11 | int libscrypt_b64_encode_compliant(unsigned char const *src, size_t srclength,
12 | /*@out@*/ char *target, size_t targetsize);
13 | int libscrypt_b64_decode_compliant(char const *src,
14 | /*@out@*/ unsigned char *target, size_t targetsize);
15 |
--------------------------------------------------------------------------------
/libscrypt/crypto-mcf.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #ifndef S_SPLINT_S /* Including this here triggers a known bug in splint */
10 | #include
11 | #endif
12 |
13 | #include "libscrypt.h"
14 |
15 | /* ilog2 for powers of two */
16 | static uint32_t scrypt_ilog2(uint32_t n)
17 | {
18 | #ifndef S_SPLINT_S
19 |
20 | /* Check for a valid power of two */
21 | if (n < 2 || (n & (n - 1)))
22 | return -1;
23 | #endif
24 | uint32_t t = 1;
25 | while (((uint32_t)1 << t) < n)
26 | {
27 | if(t > SCRYPT_SAFE_N)
28 | return (uint32_t) -1; /* Check for insanity */
29 | t++;
30 | }
31 |
32 | return t;
33 | }
34 |
35 | #ifdef _MSC_VER
36 | #define SNPRINTF _snprintf
37 | #else
38 | #define SNPRINTF snprintf
39 | #endif
40 |
41 | int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, const char *salt,
42 | const char *hash, char *mcf)
43 | {
44 |
45 | uint32_t t, params;
46 | int s;
47 |
48 | if(!mcf || !hash)
49 | return 0;
50 | /* Although larger values of r, p are valid in scrypt, this mcf format
51 | * limits to 8 bits. If your number is larger, current computers will
52 | * struggle
53 | */
54 | if(r > (uint8_t)(-1) || p > (uint8_t)(-1))
55 | return 0;
56 |
57 | t = scrypt_ilog2(N);
58 | if (t < 1)
59 | return 0;
60 |
61 | params = (r << 8) + p;
62 | params += (uint32_t)t << 16;
63 |
64 | /* Using snprintf - not checking for overflows. We've already
65 | * determined that mcf should be defined as at least SCRYPT_MCF_LEN
66 | * in length
67 | */
68 | s = SNPRINTF(mcf, SCRYPT_MCF_LEN, SCRYPT_MCF_ID "$%06x$%s$%s", (unsigned int)params, salt, hash);
69 | if (s >= SCRYPT_MCF_LEN)
70 | return 0;
71 |
72 | return 1;
73 | }
74 |
--------------------------------------------------------------------------------
/libscrypt/crypto-scrypt-saltgen.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #ifndef S_SPLINT_S /* Including this here triggers a known bug in splint */
8 | #include
9 | #endif
10 |
11 | #define RNGDEV "/dev/urandom"
12 |
13 | int libscrypt_salt_gen(uint8_t *salt, size_t len)
14 | {
15 | unsigned char buf[len];
16 | size_t data_read = 0;
17 | int urandom = open(RNGDEV, O_RDONLY);
18 |
19 | if (urandom < 0)
20 | {
21 | return -1;
22 | }
23 |
24 | while (data_read < len) {
25 | ssize_t result = read(urandom, buf + data_read, len - data_read);
26 |
27 | if (result < 0)
28 | {
29 | if (errno == EINTR || errno == EAGAIN) {
30 | continue;
31 | }
32 |
33 | else {
34 | (void)close(urandom);
35 | return -1;
36 | }
37 | }
38 |
39 | data_read += result;
40 | }
41 |
42 | /* Failures on close() shouldn't occur with O_RDONLY */
43 | (void)close(urandom);
44 |
45 | memcpy(salt, buf, len);
46 |
47 | return 0;
48 | }
49 |
--------------------------------------------------------------------------------
/libscrypt/crypto_scrypt-check.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "b64.h"
7 | #include "slowequals.h"
8 | #include "libscrypt.h"
9 |
10 | #ifdef _WIN32
11 | /* On windows, strtok uses a thread-local static variable in strtok to
12 | * make strtok thread-safe. It also neglects to provide a strtok_r. */
13 | #define strtok_r(str, val, saveptr) strtok((str), (val))
14 | #endif
15 |
16 | int libscrypt_check(char *mcf, const char *password)
17 | {
18 | /* Return values:
19 | * <0 error
20 | * == 0 password incorrect
21 | * >0 correct password
22 | */
23 |
24 | #ifndef _WIN32
25 | char *saveptr = NULL;
26 | #endif
27 | uint32_t params;
28 | uint64_t N;
29 | uint8_t r, p;
30 | int retval;
31 | uint8_t hashbuf[64];
32 | char outbuf[128];
33 | uint8_t salt[32];
34 | char *tok;
35 |
36 | if(mcf == NULL)
37 | {
38 | return -1;
39 | }
40 |
41 | if(memcmp(mcf, SCRYPT_MCF_ID, 3) != 0)
42 | {
43 | /* Only version 0 supported */
44 | return -1;
45 | }
46 |
47 | tok = strtok_r(mcf, "$", &saveptr);
48 | if ( !tok )
49 | return -1;
50 |
51 | tok = strtok_r(NULL, "$", &saveptr);
52 |
53 | if ( !tok )
54 | return -1;
55 |
56 | params = (uint32_t)strtoul(tok, NULL, 16);
57 | if ( params == 0 )
58 | return -1;
59 |
60 | tok = strtok_r(NULL, "$", &saveptr);
61 |
62 | if ( !tok )
63 | return -1;
64 |
65 | p = params & 0xff;
66 | r = (params >> 8) & 0xff;
67 | N = params >> 16;
68 |
69 | if (N > SCRYPT_SAFE_N)
70 | return -1;
71 |
72 | N = (uint64_t)1 << N;
73 |
74 | /* Useful debugging:
75 | printf("We've obtained salt 'N' r p of '%s' %d %d %d\n", tok, N,r,p);
76 | */
77 |
78 | memset(salt, 0, sizeof(salt)); /* Keeps splint happy */
79 | retval = libscrypt_b64_decode_compliant(tok, (unsigned char*)salt, sizeof(salt));
80 | if (retval < 1)
81 | return -1;
82 |
83 | retval = libscrypt_scrypt((uint8_t*)password, strlen(password), salt,
84 | (uint32_t)retval, N, r, p, hashbuf, sizeof(hashbuf));
85 |
86 | if (retval != 0)
87 | return -1;
88 |
89 | retval = libscrypt_b64_encode_compliant((unsigned char*)hashbuf, sizeof(hashbuf),
90 | outbuf, sizeof(outbuf));
91 |
92 | if (retval == 0)
93 | return -1;
94 |
95 | tok = strtok_r(NULL, "$", &saveptr);
96 |
97 | if ( !tok )
98 | return -1;
99 |
100 | if(slow_equals(tok, outbuf) == 0)
101 | return 0;
102 |
103 | return 1; /* This is the "else" condition */
104 | }
105 |
106 |
--------------------------------------------------------------------------------
/libscrypt/crypto_scrypt-hash.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "b64.h"
7 | #include "libscrypt.h"
8 |
9 | int libscrypt_hash(char *dst, const char *passphrase, uint32_t N, uint8_t r,
10 | uint8_t p)
11 | {
12 |
13 | int retval;
14 | uint8_t salt[SCRYPT_SALT_LEN];
15 | uint8_t hashbuf[SCRYPT_HASH_LEN];
16 | char outbuf[256];
17 | char saltbuf[256];
18 |
19 | if(libscrypt_salt_gen(salt, SCRYPT_SALT_LEN) == -1)
20 | {
21 | return 0;
22 | }
23 |
24 | retval = libscrypt_scrypt((const uint8_t*)passphrase, strlen(passphrase),
25 | (uint8_t*)salt, SCRYPT_SALT_LEN, N, r, p, hashbuf, sizeof(hashbuf));
26 | if(retval == -1)
27 | return 0;
28 |
29 | retval = libscrypt_b64_encode_compliant((unsigned char*)hashbuf, sizeof(hashbuf),
30 | outbuf, sizeof(outbuf));
31 | if(retval == -1)
32 | return 0;
33 |
34 | retval = libscrypt_b64_encode_compliant((unsigned char *)salt, sizeof(salt),
35 | saltbuf, sizeof(saltbuf));
36 | if(retval == -1)
37 | return 0;
38 |
39 | retval = libscrypt_mcf(N, r, p, saltbuf, outbuf, dst);
40 | if(retval != 1)
41 | return 0;
42 |
43 | return 1;
44 | }
45 |
--------------------------------------------------------------------------------
/libscrypt/crypto_scrypt-hexconvert.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | /* The hexconvert function is only used to test reference vectors against
7 | * known answers. The contents of this file are therefore a component
8 | * to assist with test harnesses only
9 | */
10 |
11 | int libscrypt_hexconvert(const unsigned char * buf, size_t s, char *outbuf, size_t obs)
12 | {
13 | size_t i;
14 | int len = 0;
15 |
16 | if (!buf || s < 1 || obs < (s * 2 + 1))
17 | return 0;
18 |
19 | memset(outbuf, 0, obs);
20 |
21 | for(i=0; i<=(s-1); i++)
22 | {
23 | /* snprintf(outbuf, s,"%s...", outbuf....) has undefined results
24 | * and can't be used. Using offests like this makes snprintf
25 | * nontrivial. we therefore have use inescure sprintf() and
26 | * lengths checked elsewhere (start of function) */
27 | /*@ -bufferoverflowhigh @*/
28 | len += sprintf(outbuf+len, "%02x", (unsigned int) buf[i]);
29 | }
30 |
31 | return 1;
32 | }
33 |
34 | int libscrypt_hex_encode(const unsigned char * buf, size_t s, char *outbuf, size_t obs)
35 | {
36 | return libscrypt_hexconvert(buf, s, outbuf, obs);
37 | }
38 |
--------------------------------------------------------------------------------
/libscrypt/crypto_scrypt-hexconvert.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | /**
5 | * Converts a binary string to a hex representation of that string
6 | * outbuf must have size of at least buf * 2 + 1.
7 | */
8 | int libscrypt_hexconvert(const unsigned char * buf, size_t s, char *outbuf, size_t obs);
9 | int libscrypt_hex_encode(const unsigned char * buf, size_t s, char *outbuf, size_t obs);
10 |
--------------------------------------------------------------------------------
/libscrypt/crypto_scrypt-nosse.c:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2009 Colin Percival
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 | * SUCH DAMAGE.
25 | *
26 | * This file was originally written by Colin Percival as part of the Tarsnap
27 | * online backup system.
28 | */
29 |
30 | #include
31 | #ifndef _WIN32
32 | #include
33 | #endif
34 | #include
35 | #include
36 | #include
37 | #include
38 |
39 | #include "sha256.h"
40 | #include "sysendian.h"
41 |
42 | #include "libscrypt.h"
43 |
44 | static void blkcpy(void *, void *, size_t);
45 | static void blkxor(void *, void *, size_t);
46 | static void salsa20_8(uint32_t[16]);
47 | static void blockmix_salsa8(uint32_t *, uint32_t *, uint32_t *, size_t);
48 | static uint64_t integerify(void *, size_t);
49 | static void smix(uint8_t *, size_t, uint64_t, uint32_t *, uint32_t *);
50 |
51 | static void
52 | blkcpy(void * dest, void * src, size_t len)
53 | {
54 | size_t * D = dest;
55 | size_t * S = src;
56 | size_t L = len / sizeof(size_t);
57 | size_t i;
58 |
59 | for (i = 0; i < L; i++)
60 | D[i] = S[i];
61 | }
62 |
63 | static void
64 | blkxor(void * dest, void * src, size_t len)
65 | {
66 | size_t * D = dest;
67 | size_t * S = src;
68 | size_t L = len / sizeof(size_t);
69 | size_t i;
70 |
71 | for (i = 0; i < L; i++)
72 | D[i] ^= S[i];
73 | }
74 |
75 | /**
76 | * salsa20_8(B):
77 | * Apply the salsa20/8 core to the provided block.
78 | */
79 | static void
80 | salsa20_8(uint32_t B[16])
81 | {
82 | uint32_t x[16];
83 | size_t i;
84 |
85 | blkcpy(x, B, 64);
86 | for (i = 0; i < 8; i += 2) {
87 | #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
88 | /* Operate on columns. */
89 | x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
90 | x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
91 |
92 | x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
93 | x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
94 |
95 | x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
96 | x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
97 |
98 | x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
99 | x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
100 |
101 | /* Operate on rows. */
102 | x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
103 | x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
104 |
105 | x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
106 | x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
107 |
108 | x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
109 | x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
110 |
111 | x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
112 | x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
113 | #undef R
114 | }
115 | for (i = 0; i < 16; i++)
116 | B[i] += x[i];
117 | }
118 |
119 | /**
120 | * blockmix_salsa8(Bin, Bout, X, r):
121 | * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
122 | * bytes in length; the output Bout must also be the same size. The
123 | * temporary space X must be 64 bytes.
124 | */
125 | static void
126 | blockmix_salsa8(uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)
127 | {
128 | size_t i;
129 |
130 | /* 1: X <-- B_{2r - 1} */
131 | blkcpy(X, &Bin[(2 * r - 1) * 16], 64);
132 |
133 | /* 2: for i = 0 to 2r - 1 do */
134 | for (i = 0; i < 2 * r; i += 2) {
135 | /* 3: X <-- H(X \xor B_i) */
136 | blkxor(X, &Bin[i * 16], 64);
137 | salsa20_8(X);
138 |
139 | /* 4: Y_i <-- X */
140 | /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
141 | blkcpy(&Bout[i * 8], X, 64);
142 |
143 | /* 3: X <-- H(X \xor B_i) */
144 | blkxor(X, &Bin[i * 16 + 16], 64);
145 | salsa20_8(X);
146 |
147 | /* 4: Y_i <-- X */
148 | /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
149 | blkcpy(&Bout[i * 8 + r * 16], X, 64);
150 | }
151 | }
152 |
153 | /**
154 | * integerify(B, r):
155 | * Return the result of parsing B_{2r-1} as a little-endian integer.
156 | */
157 | static uint64_t
158 | integerify(void * B, size_t r)
159 | {
160 | uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64);
161 |
162 | return (((uint64_t)(X[1]) << 32) + X[0]);
163 | }
164 |
165 | /**
166 | * smix(B, r, N, V, XY):
167 | * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
168 | * the temporary storage V must be 128rN bytes in length; the temporary
169 | * storage XY must be 256r + 64 bytes in length. The value N must be a
170 | * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
171 | * multiple of 64 bytes.
172 | */
173 | static void
174 | smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY)
175 | {
176 | uint32_t * X = XY;
177 | uint32_t * Y = &XY[32 * r];
178 | uint32_t * Z = &XY[64 * r];
179 | uint64_t i;
180 | uint64_t j;
181 | size_t k;
182 |
183 | /* 1: X <-- B */
184 | for (k = 0; k < 32 * r; k++)
185 | X[k] = le32dec(&B[4 * k]);
186 |
187 | /* 2: for i = 0 to N - 1 do */
188 | for (i = 0; i < N; i += 2) {
189 | /* 3: V_i <-- X */
190 | blkcpy(&V[i * (32 * r)], X, 128 * r);
191 |
192 | /* 4: X <-- H(X) */
193 | blockmix_salsa8(X, Y, Z, r);
194 |
195 | /* 3: V_i <-- X */
196 | blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r);
197 |
198 | /* 4: X <-- H(X) */
199 | blockmix_salsa8(Y, X, Z, r);
200 | }
201 |
202 | /* 6: for i = 0 to N - 1 do */
203 | for (i = 0; i < N; i += 2) {
204 | /* 7: j <-- Integerify(X) mod N */
205 | j = integerify(X, r) & (N - 1);
206 |
207 | /* 8: X <-- H(X \xor V_j) */
208 | blkxor(X, &V[j * (32 * r)], 128 * r);
209 | blockmix_salsa8(X, Y, Z, r);
210 |
211 | /* 7: j <-- Integerify(X) mod N */
212 | j = integerify(Y, r) & (N - 1);
213 |
214 | /* 8: X <-- H(X \xor V_j) */
215 | blkxor(Y, &V[j * (32 * r)], 128 * r);
216 | blockmix_salsa8(Y, X, Z, r);
217 | }
218 |
219 | /* 10: B' <-- X */
220 | for (k = 0; k < 32 * r; k++)
221 | le32enc(&B[4 * k], X[k]);
222 | }
223 |
224 | /**
225 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
226 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
227 | * p, buflen) and write the result into buf. The parameters r, p, and buflen
228 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
229 | * must be a power of 2 greater than 1.
230 | *
231 | * Return 0 on success; or -1 on error
232 | */
233 | int
234 | libscrypt_scrypt(const uint8_t * passwd, size_t passwdlen,
235 | const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
236 | uint8_t * buf, size_t buflen)
237 | {
238 | void * B0, * V0, * XY0;
239 | uint8_t * B;
240 | uint32_t * V;
241 | uint32_t * XY;
242 | uint32_t i;
243 |
244 | /* Sanity-check parameters. */
245 | #if SIZE_MAX > UINT32_MAX
246 | if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
247 | errno = EFBIG;
248 | goto err0;
249 | }
250 | #endif
251 | if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
252 | errno = EFBIG;
253 | goto err0;
254 | }
255 | if (r == 0 || p == 0) {
256 | errno = EINVAL;
257 | goto err0;
258 | }
259 | if (((N & (N - 1)) != 0) || (N < 2)) {
260 | errno = EINVAL;
261 | goto err0;
262 | }
263 | if ((r > SIZE_MAX / 128 / p) ||
264 | #if SIZE_MAX / 256 <= UINT32_MAX
265 | (r > SIZE_MAX / 256) ||
266 | #endif
267 | (N > SIZE_MAX / 128 / r)) {
268 | errno = ENOMEM;
269 | goto err0;
270 | }
271 |
272 | /* Allocate memory. */
273 | #ifdef HAVE_POSIX_MEMALIGN
274 | if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)
275 | goto err0;
276 | B = (uint8_t *)(B0);
277 | if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)
278 | goto err1;
279 | XY = (uint32_t *)(XY0);
280 | #ifndef MAP_ANON
281 | if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)
282 | goto err2;
283 | V = (uint32_t *)(V0);
284 | #endif
285 | #else
286 | if ((B0 = malloc(128 * r * p + 63)) == NULL)
287 | goto err0;
288 | B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));
289 | if ((XY0 = malloc(256 * r + 64 + 63)) == NULL)
290 | goto err1;
291 | XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
292 | #ifndef MAP_ANON
293 | if ((V0 = malloc(128 * r * N + 63)) == NULL)
294 | goto err2;
295 | V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
296 | #endif
297 | #endif
298 | #ifdef MAP_ANON
299 | if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,
300 | #ifdef MAP_NOCORE
301 | MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
302 | #else
303 | MAP_ANON | MAP_PRIVATE,
304 | #endif
305 | -1, 0)) == MAP_FAILED)
306 | goto err2;
307 | V = (uint32_t *)(V0);
308 | #endif
309 |
310 | /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
311 | libscrypt_PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
312 |
313 | /* 2: for i = 0 to p - 1 do */
314 | for (i = 0; i < p; i++) {
315 | /* 3: B_i <-- MF(B_i, N) */
316 | smix(&B[i * 128 * r], r, N, V, XY);
317 | }
318 |
319 | /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
320 | libscrypt_PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
321 |
322 | /* Free memory. */
323 | #ifdef MAP_ANON
324 | if (munmap(V0, 128 * r * N))
325 | goto err2;
326 | #else
327 | free(V0);
328 | #endif
329 | free(XY0);
330 | free(B0);
331 |
332 | /* Success! */
333 | return (0);
334 |
335 | err2:
336 | free(XY0);
337 | err1:
338 | free(B0);
339 | err0:
340 | /* Failure! */
341 | return (-1);
342 | }
343 |
--------------------------------------------------------------------------------
/libscrypt/libscrypt.h:
--------------------------------------------------------------------------------
1 | /*-
2 | */
3 | #ifndef _CRYPTO_SCRYPT_H_
4 | #define _CRYPTO_SCRYPT_H_
5 |
6 |
7 | #include
8 | #include
9 | #ifdef __cplusplus
10 | extern "C"{
11 | #endif
12 |
13 | #include "crypto_scrypt-hexconvert.h"
14 |
15 | /**
16 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
17 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
18 | * p, buflen) and write the result into buf. The parameters r, p, and buflen
19 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
20 | * must be a power of 2 greater than 1.
21 | *
22 | * libscrypt_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
23 | * password; duh
24 | * N: CPU AND RAM cost (first modifier)
25 | * r: RAM Cost
26 | * p: CPU cost (parallelisation)
27 | * In short, N is your main performance modifier. Values of r = 8, p = 1 are
28 | * standard unless you want to modify the CPU/RAM ratio.
29 | * Return 0 on success; or -1 on error.
30 | */
31 | int libscrypt_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t,
32 | uint32_t, uint32_t, /*@out@*/ uint8_t *, size_t);
33 |
34 | /* Converts a series of input parameters to a MCF form for storage */
35 | int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, const char *salt,
36 | const char *hash, char *mcf);
37 |
38 | #ifndef _MSC_VER
39 | /* Generates a salt. Uses /dev/urandom/
40 | */
41 | int libscrypt_salt_gen(/*@out@*/ uint8_t *rand, size_t len);
42 |
43 | /* Creates a hash of a passphrase using a randomly generated salt */
44 | /* Returns >0 on success, or 0 for fail */
45 | int libscrypt_hash(char *dst, const char* passphrase, uint32_t N, uint8_t r,
46 | uint8_t p);
47 | #endif
48 |
49 | /* Checks a given MCF against a password */
50 | int libscrypt_check(char *mcf, const char *password);
51 |
52 | #ifdef __cplusplus
53 | }
54 | #endif
55 |
56 | /* Sane default values */
57 | #define SCRYPT_HASH_LEN 64 /* This can be user defined -
58 | *but 64 is the reference size
59 | */
60 | #define SCRYPT_SAFE_N 30 /* This is much higher than you want. It's just
61 | * a blocker for insane defines
62 | */
63 | #define SCRYPT_SALT_LEN 16 /* This is just a recommended size */
64 | /* Standard MCF is:
65 | $s1 Identifier, three chars
66 | $0e0810 Work order and separator, six chars
67 | Formula for binary to base64 length = ceil(n/3)*4
68 | $pcL+DWle903AXcKJVwMffA== Salt is 16 bytes, or 24 in Base64
69 | $dn+9ujljVc5JTJMC2fYu1ZEHdJyqYkOurmcrBQbMHUfnD6qxbTmNiR075ohNBZjvp66E2aV1pfOrmyNHUefjMg== Hash is 64 bytes, or 88 in Base64.
70 | Work order, salt and hash have separators (3)
71 | 3 + 6 + 24 + 88 + 3 + null byte = 125
72 | This is rounded up to a multiple of four for alignment
73 | */
74 | #define SCRYPT_MCF_LEN 128
75 | #define SCRYPT_MCF_ID "$s1"
76 | #define SCRYPT_N 16384
77 | #define SCRYPT_r 8
78 | #define SCRYPT_p 16
79 | #endif /* !_CRYPTO_SCRYPT_H_ */
80 |
--------------------------------------------------------------------------------
/libscrypt/libscrypt.version:
--------------------------------------------------------------------------------
1 | libscrypt {
2 | global: libscrypt_check;
3 | libscrypt_hash;
4 | libscrypt_mcf;
5 | libscrypt_salt_gen;
6 | libscrypt_scrypt;
7 | local: *;
8 | };
9 |
--------------------------------------------------------------------------------
/libscrypt/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "b64.h"
7 | #include "crypto_scrypt-hexconvert.h"
8 | #include "libscrypt.h"
9 |
10 | #define REF1 "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640"
11 |
12 | #define REF2 "7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887"
13 |
14 |
15 | int main()
16 | {
17 | uint8_t hashbuf[SCRYPT_HASH_LEN];
18 | char outbuf[132];
19 | char mcf[SCRYPT_MCF_LEN];
20 | char mcf2[SCRYPT_MCF_LEN];
21 | char saltbuf[64];
22 | int retval;
23 | /**
24 | * libscrypt_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
25 | * password; duh
26 | * N: CPU AND RAM cost (first modifier)
27 | * r: RAM Cost
28 | * p: CPU cost (parallelisation)
29 | * In short, N is your main performance modifier. Values of r = 8, p = 1 are
30 | * standard unless you want to modify the CPU/RAM ratio.
31 | int libscrypt_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t,
32 | uint32_t, uint32_t, uint8_t *, size_t);
33 | */
34 |
35 | printf("TEST ONE: Direct call to reference function with password 'password' and salt 'NaCL'\n");
36 |
37 | retval = libscrypt_scrypt((uint8_t*)"password",strlen("password"), (uint8_t*)"NaCl", strlen("NaCl"), 1024, 8, 16, hashbuf, sizeof(hashbuf));
38 |
39 | if(retval != 0)
40 | {
41 | printf("TEST ONE FAILED: Failed to create hash of \"password\"\\n");
42 | exit(EXIT_FAILURE);
43 | }
44 |
45 | printf("TEST ONE: SUCCESSFUL\n");
46 |
47 | printf("TEST ONE and a half: Review errno on invalid input\n");
48 |
49 | retval = libscrypt_scrypt((uint8_t*)"password",strlen("password"), (uint8_t*)"NaCl", strlen("NaCl"), 47, 1, 1, hashbuf, sizeof(hashbuf));
50 |
51 | if(retval != -1)
52 | {
53 | printf("TEST ONE FAILED: Failed to detect invalid input\n");
54 | exit(EXIT_FAILURE);
55 | }
56 | printf("TEST ONE and a half: Successfully failed on error: %s\n", strerror(errno));
57 |
58 | /* Convert the binary string to hex representation. Outbuf must be
59 | * at least sizeof(hashbuf) * 2 + 1
60 | * Returns 0 on fail, 1 on success
61 | */
62 | printf("TEST TWO: Convert binary output to hex\n");
63 | retval = libscrypt_hexconvert(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf));
64 | if(!retval)
65 | {
66 | printf("TEST TWO: FAILED\n");
67 | exit(EXIT_FAILURE);
68 | }
69 | printf("TEST TWO: SUCCESSFUL, Hex output is:\n%s\n", outbuf);
70 |
71 | printf("TEST THREE: Compare hex output to reference hash output\n");
72 |
73 | /* REF1 is a reference vector from Colin's implementation. */
74 | if(strcmp(outbuf, REF1) != 0)
75 | {
76 | printf("TEST THREE: FAILED to match reference on hash\n");
77 | exit(EXIT_FAILURE);
78 | }
79 | else
80 | {
81 | printf("TEST THREE: SUCCESSUL, Test vector matched!\n");
82 | }
83 |
84 | printf("TEST FOUR: Direct call to reference function with pleaseletmein password and SodiumChloride as salt\n");
85 |
86 | /* Tests 4-6 repeat tests 1-3 with a different reference vector */
87 |
88 | retval = libscrypt_scrypt((uint8_t*)"pleaseletmein",strlen("pleaseletmein"), (uint8_t*)"SodiumChloride", strlen("SodiumChloride"), 16384, 8, 1, hashbuf, sizeof(hashbuf));
89 |
90 | if(retval != 0)
91 | {
92 | printf("TEST FOUR FAILED: Failed to create hash of 'pleaseletmein'\n");
93 | exit(EXIT_FAILURE);
94 | }
95 |
96 | printf("TEST FOUR: SUCCESSFUL\n");
97 |
98 | /* Convert the binary string to hex representation. Outbuf must be
99 | * at least sizeof(hashbuf) * 2 + 1
100 | */
101 | printf("TEST FIVE: Convert binary output to hex\n");
102 | retval = libscrypt_hexconvert(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf));
103 | if(!retval)
104 | {
105 | printf("TEST FIVE: FAILED\n");
106 | exit(EXIT_FAILURE);
107 | }
108 | printf("TEST FIVE: SUCCESSFUL, Hex output is:\n%s\n", outbuf);
109 |
110 | printf("TEST SIX: Compare hex output to reference hash output\n");
111 |
112 | if(strcmp(outbuf, REF2) != 0)
113 | {
114 | printf("TEST SIX: FAILED to match reference on hash\n");
115 | exit(EXIT_FAILURE);
116 | }
117 | else
118 | {
119 | printf("TEST SIX: SUCCESSUL, Test vector matched!\n");
120 | }
121 |
122 | /* This function will convert the binary output to BASE64. Although
123 | * we converted to hex for the reference vectors, BASE64 is more useful.
124 | * Returns -1 on error, else returns length.
125 | * Correct buffer length can be determined using the below function if
126 | retuired.
127 | * char* dest = (char*) malloc(modp_b64_encode_len);
128 | * Note that this is not an exported function
129 | */
130 |
131 | printf("TEST SEVEN: BASE64 encoding the salt and hash output\n");
132 |
133 | retval = libscrypt_b64_encode_compliant(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf));
134 | if(retval == -1)
135 | {
136 | printf("TEST SEVEN FAILED\n");
137 | exit(EXIT_FAILURE);
138 | }
139 | retval = libscrypt_b64_encode_compliant((unsigned char*)"SodiumChloride", strlen("SodiumChloride"), saltbuf, sizeof(saltbuf));
140 | if(retval == -1)
141 | {
142 | printf("TEST SEVEN FAILED\n");
143 | exit(EXIT_FAILURE);
144 | }
145 |
146 | printf("TEST SEVEN: SUCCESSFUL\n");
147 |
148 | printf("TEST EIGHT: Create an MCF format output\n");
149 |
150 | /* Creates a standard format output
151 | * int crypto_scrypt_mcf(uint32_t N, uint32_t r, uint32_t p, char *salt, char *hash, char *mcf);
152 | * Returns 0 on error, most likely reason is log2(N) not an integer.
153 | */
154 | retval = libscrypt_mcf(16384, 8, 1, saltbuf, outbuf, mcf);
155 | if(!retval)
156 | {
157 | printf("TEST EIGHT FAILED\n");
158 | exit(EXIT_FAILURE);
159 | }
160 |
161 | printf("TEST EIGHT: SUCCESSFUL, calculated mcf\n%s\n", mcf);
162 |
163 | /* Since later calls to scrypt_check() butcher mcf, make a second */
164 | strcpy(mcf2, mcf);
165 |
166 | /* Couldn't be simpler - for a given mcf, check is the password is valid
167 | * Returns < 0 on failure to calculate hash
168 | * 0 if password incorrect
169 | * >1 if password correct
170 | */
171 |
172 | printf("TEST NINE: Password verify on given MCF\n");
173 | retval = libscrypt_check(mcf, "pleaseletmein");
174 |
175 | if(retval < 0)
176 | {
177 | printf("TEST NINE: FAILED, hash failed to calculate\n");
178 | exit(EXIT_FAILURE);
179 | }
180 | if(retval == 0)
181 | {
182 | printf("TEST NINE: FAILED, claimed pleaseletmein hash claimed did not verify\n");
183 | exit(EXIT_FAILURE);
184 | }
185 | /* retval >0 is a success */
186 | printf("TEST NINE: SUCCESSFUL, tested pleaseletmein password\n");
187 |
188 | printf("TEST TEN: Password verify on same MCF, incorrect password\n");
189 | retval = libscrypt_check(mcf2, "pleasefailme");
190 |
191 | if(retval < 0)
192 | {
193 | printf("TEST TEN: FAILED, hash failed to calculate\n");
194 | exit(EXIT_FAILURE);
195 | }
196 | if(retval > 0)
197 | {
198 | printf("TEST TEN: FAILED, fail hash has passed\n");
199 | exit(EXIT_FAILURE);
200 | }
201 |
202 | printf("TEST TEN: SUCCESSFUL, refused incorrect password\n");
203 |
204 | printf("TEST ELEVEN: Testing salt generator\n");
205 |
206 | retval = libscrypt_salt_gen((uint8_t*)saltbuf, SCRYPT_SALT_LEN);
207 | if(retval == -1)
208 | {
209 | printf("TEST ELEVEN (salt generate) FAILED\n");
210 | exit(EXIT_FAILURE);
211 | }
212 |
213 | retval = libscrypt_b64_encode_compliant((uint8_t*)saltbuf, SCRYPT_SALT_LEN, outbuf, sizeof(outbuf));
214 | if(retval == -1)
215 | {
216 | printf("TEST ELEVEN (b64 encode) FAILED\n");
217 | exit(EXIT_FAILURE);
218 | }
219 | printf("TEST ELEVEN: SUCCESSFUL, Generated %s\n", outbuf);
220 |
221 | printf("TEST TWELVE: Simple hash creation\n");
222 |
223 | retval = libscrypt_hash(outbuf, "My cats's breath smells like cat food", SCRYPT_N, SCRYPT_r, SCRYPT_p);
224 | if(!retval)
225 | {
226 | printf("TEST TWELVE: FAILED, Failed to create simple hash\n");
227 | exit(EXIT_FAILURE);
228 | }
229 | printf("TEST TWELVE: SUCCESSFUL. Received the following from simple hash:\n%s\n", outbuf);
230 |
231 | printf("TEST THIRTEEN: Verify test twelve's hash\n");
232 |
233 | retval = libscrypt_check(outbuf, "My cats's breath smells like cat food");
234 |
235 | if (retval != 1) {
236 | printf("TEST THIRTEEN: FAILED, hash not verified\n");
237 | exit(EXIT_FAILURE);
238 | }
239 |
240 | printf("TEST THIRTEEN: SUCCESSFUL\n");
241 |
242 | return 0;
243 | }
244 |
245 |
--------------------------------------------------------------------------------
/libscrypt/sha256.c:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2005,2007,2009 Colin Percival
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 | * SUCH DAMAGE.
25 | */
26 |
27 | #include
28 |
29 | #include
30 | #include
31 |
32 | #include "sysendian.h"
33 |
34 | #include "sha256.h"
35 |
36 | /*
37 | * Encode a length len/4 vector of (uint32_t) into a length len vector of
38 | * (unsigned char) in big-endian form. Assumes len is a multiple of 4.
39 | */
40 | static void
41 | be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
42 | {
43 | size_t i;
44 |
45 | for (i = 0; i < len / 4; i++)
46 | be32enc(dst + i * 4, src[i]);
47 | }
48 |
49 | /*
50 | * Decode a big-endian length len vector of (unsigned char) into a length
51 | * len/4 vector of (uint32_t). Assumes len is a multiple of 4.
52 | */
53 | static void
54 | be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
55 | {
56 | size_t i;
57 |
58 | for (i = 0; i < len / 4; i++)
59 | dst[i] = be32dec(src + i * 4);
60 | }
61 |
62 | /* Elementary functions used by SHA256 */
63 | #define Ch(x, y, z) ((x & (y ^ z)) ^ z)
64 | #define Maj(x, y, z) ((x & (y | z)) | (y & z))
65 | #define SHR(x, n) (x >> n)
66 | #define ROTR(x, n) ((x >> n) | (x << (32 - n)))
67 | #define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
68 | #define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
69 | #define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
70 | #define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
71 |
72 | /* SHA256 round function */
73 | #define RND(a, b, c, d, e, f, g, h, k) \
74 | t0 = h + S1(e) + Ch(e, f, g) + k; \
75 | t1 = S0(a) + Maj(a, b, c); \
76 | d += t0; \
77 | h = t0 + t1;
78 |
79 | /* Adjusted round function for rotating state */
80 | #define RNDr(S, W, i, k) \
81 | RND(S[(64 - i) % 8], S[(65 - i) % 8], \
82 | S[(66 - i) % 8], S[(67 - i) % 8], \
83 | S[(68 - i) % 8], S[(69 - i) % 8], \
84 | S[(70 - i) % 8], S[(71 - i) % 8], \
85 | W[i] + k)
86 |
87 | /*
88 | * SHA256 block compression function. The 256-bit state is transformed via
89 | * the 512-bit input block to produce a new state.
90 | */
91 | static void
92 | SHA256_Transform(uint32_t * state, const unsigned char block[64])
93 | {
94 | uint32_t W[64];
95 | uint32_t S[8];
96 | uint32_t t0, t1;
97 | int i;
98 |
99 | /* 1. Prepare message schedule W. */
100 | be32dec_vect(W, block, 64);
101 | for (i = 16; i < 64; i++)
102 | W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
103 |
104 | /* 2. Initialize working variables. */
105 | memcpy(S, state, 32);
106 |
107 | /* 3. Mix. */
108 | RNDr(S, W, 0, 0x428a2f98);
109 | RNDr(S, W, 1, 0x71374491);
110 | RNDr(S, W, 2, 0xb5c0fbcf);
111 | RNDr(S, W, 3, 0xe9b5dba5);
112 | RNDr(S, W, 4, 0x3956c25b);
113 | RNDr(S, W, 5, 0x59f111f1);
114 | RNDr(S, W, 6, 0x923f82a4);
115 | RNDr(S, W, 7, 0xab1c5ed5);
116 | RNDr(S, W, 8, 0xd807aa98);
117 | RNDr(S, W, 9, 0x12835b01);
118 | RNDr(S, W, 10, 0x243185be);
119 | RNDr(S, W, 11, 0x550c7dc3);
120 | RNDr(S, W, 12, 0x72be5d74);
121 | RNDr(S, W, 13, 0x80deb1fe);
122 | RNDr(S, W, 14, 0x9bdc06a7);
123 | RNDr(S, W, 15, 0xc19bf174);
124 | RNDr(S, W, 16, 0xe49b69c1);
125 | RNDr(S, W, 17, 0xefbe4786);
126 | RNDr(S, W, 18, 0x0fc19dc6);
127 | RNDr(S, W, 19, 0x240ca1cc);
128 | RNDr(S, W, 20, 0x2de92c6f);
129 | RNDr(S, W, 21, 0x4a7484aa);
130 | RNDr(S, W, 22, 0x5cb0a9dc);
131 | RNDr(S, W, 23, 0x76f988da);
132 | RNDr(S, W, 24, 0x983e5152);
133 | RNDr(S, W, 25, 0xa831c66d);
134 | RNDr(S, W, 26, 0xb00327c8);
135 | RNDr(S, W, 27, 0xbf597fc7);
136 | RNDr(S, W, 28, 0xc6e00bf3);
137 | RNDr(S, W, 29, 0xd5a79147);
138 | RNDr(S, W, 30, 0x06ca6351);
139 | RNDr(S, W, 31, 0x14292967);
140 | RNDr(S, W, 32, 0x27b70a85);
141 | RNDr(S, W, 33, 0x2e1b2138);
142 | RNDr(S, W, 34, 0x4d2c6dfc);
143 | RNDr(S, W, 35, 0x53380d13);
144 | RNDr(S, W, 36, 0x650a7354);
145 | RNDr(S, W, 37, 0x766a0abb);
146 | RNDr(S, W, 38, 0x81c2c92e);
147 | RNDr(S, W, 39, 0x92722c85);
148 | RNDr(S, W, 40, 0xa2bfe8a1);
149 | RNDr(S, W, 41, 0xa81a664b);
150 | RNDr(S, W, 42, 0xc24b8b70);
151 | RNDr(S, W, 43, 0xc76c51a3);
152 | RNDr(S, W, 44, 0xd192e819);
153 | RNDr(S, W, 45, 0xd6990624);
154 | RNDr(S, W, 46, 0xf40e3585);
155 | RNDr(S, W, 47, 0x106aa070);
156 | RNDr(S, W, 48, 0x19a4c116);
157 | RNDr(S, W, 49, 0x1e376c08);
158 | RNDr(S, W, 50, 0x2748774c);
159 | RNDr(S, W, 51, 0x34b0bcb5);
160 | RNDr(S, W, 52, 0x391c0cb3);
161 | RNDr(S, W, 53, 0x4ed8aa4a);
162 | RNDr(S, W, 54, 0x5b9cca4f);
163 | RNDr(S, W, 55, 0x682e6ff3);
164 | RNDr(S, W, 56, 0x748f82ee);
165 | RNDr(S, W, 57, 0x78a5636f);
166 | RNDr(S, W, 58, 0x84c87814);
167 | RNDr(S, W, 59, 0x8cc70208);
168 | RNDr(S, W, 60, 0x90befffa);
169 | RNDr(S, W, 61, 0xa4506ceb);
170 | RNDr(S, W, 62, 0xbef9a3f7);
171 | RNDr(S, W, 63, 0xc67178f2);
172 |
173 | /* 4. Mix local working variables into global state */
174 | for (i = 0; i < 8; i++)
175 | state[i] += S[i];
176 |
177 | /* Clean the stack. */
178 | memset(W, 0, 256);
179 | memset(S, 0, 32);
180 | t0 = t1 = 0;
181 | }
182 |
183 | static unsigned char PAD[64] = {
184 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
185 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
186 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
187 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
188 | };
189 |
190 | /* Add padding and terminating bit-count. */
191 | static void
192 | SHA256_Pad(SHA256_CTX * ctx)
193 | {
194 | unsigned char len[8];
195 | uint32_t r, plen;
196 |
197 | /*
198 | * Convert length to a vector of bytes -- we do this now rather
199 | * than later because the length will change after we pad.
200 | */
201 | be32enc_vect(len, ctx->count, 8);
202 |
203 | /* Add 1--64 bytes so that the resulting length is 56 mod 64 */
204 | r = (ctx->count[1] >> 3) & 0x3f;
205 | plen = (r < 56) ? (56 - r) : (120 - r);
206 | libscrypt_SHA256_Update(ctx, PAD, (size_t)plen);
207 |
208 | /* Add the terminating bit-count */
209 | libscrypt_SHA256_Update(ctx, len, 8);
210 | }
211 |
212 | /* SHA-256 initialization. Begins a SHA-256 operation. */
213 | void
214 | libscrypt_SHA256_Init(SHA256_CTX * ctx)
215 | {
216 |
217 | /* Zero bits processed so far */
218 | ctx->count[0] = ctx->count[1] = 0;
219 |
220 | /* Magic initialization constants */
221 | ctx->state[0] = 0x6A09E667;
222 | ctx->state[1] = 0xBB67AE85;
223 | ctx->state[2] = 0x3C6EF372;
224 | ctx->state[3] = 0xA54FF53A;
225 | ctx->state[4] = 0x510E527F;
226 | ctx->state[5] = 0x9B05688C;
227 | ctx->state[6] = 0x1F83D9AB;
228 | ctx->state[7] = 0x5BE0CD19;
229 | }
230 |
231 | /* Add bytes into the hash */
232 | void
233 | libscrypt_SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len)
234 | {
235 | uint32_t bitlen[2];
236 | uint32_t r;
237 | const unsigned char *src = in;
238 |
239 | /* Number of bytes left in the buffer from previous updates */
240 | r = (ctx->count[1] >> 3) & 0x3f;
241 |
242 | /* Convert the length into a number of bits */
243 | bitlen[1] = ((uint32_t)len) << 3;
244 | bitlen[0] = (uint32_t)(len >> 29);
245 |
246 | /* Update number of bits */
247 | if ((ctx->count[1] += bitlen[1]) < bitlen[1])
248 | ctx->count[0]++;
249 | ctx->count[0] += bitlen[0];
250 |
251 | /* Handle the case where we don't need to perform any transforms */
252 | if (len < 64 - r) {
253 | memcpy(&ctx->buf[r], src, len);
254 | return;
255 | }
256 |
257 | /* Finish the current block */
258 | memcpy(&ctx->buf[r], src, 64 - r);
259 | SHA256_Transform(ctx->state, ctx->buf);
260 | src += 64 - r;
261 | len -= 64 - r;
262 |
263 | /* Perform complete blocks */
264 | while (len >= 64) {
265 | SHA256_Transform(ctx->state, src);
266 | src += 64;
267 | len -= 64;
268 | }
269 |
270 | /* Copy left over data into buffer */
271 | memcpy(ctx->buf, src, len);
272 | }
273 |
274 | /*
275 | * SHA-256 finalization. Pads the input data, exports the hash value,
276 | * and clears the context state.
277 | */
278 | void
279 | libscrypt_SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx)
280 | {
281 |
282 | /* Add padding */
283 | SHA256_Pad(ctx);
284 |
285 | /* Write the hash */
286 | be32enc_vect(digest, ctx->state, 32);
287 |
288 | /* Clear the context state */
289 | memset((void *)ctx, 0, sizeof(*ctx));
290 | }
291 |
292 | /* Initialize an HMAC-SHA256 operation with the given key. */
293 | void
294 | libscrypt_HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
295 | {
296 | unsigned char pad[64];
297 | unsigned char khash[32];
298 | const unsigned char * K = _K;
299 | size_t i;
300 |
301 | /* If Klen > 64, the key is really SHA256(K). */
302 | if (Klen > 64) {
303 | libscrypt_SHA256_Init(&ctx->ictx);
304 | libscrypt_SHA256_Update(&ctx->ictx, K, Klen);
305 | libscrypt_SHA256_Final(khash, &ctx->ictx);
306 | K = khash;
307 | Klen = 32;
308 | }
309 |
310 | /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
311 | libscrypt_SHA256_Init(&ctx->ictx);
312 | memset(pad, 0x36, 64);
313 | for (i = 0; i < Klen; i++)
314 | pad[i] ^= K[i];
315 | libscrypt_SHA256_Update(&ctx->ictx, pad, 64);
316 |
317 | /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
318 | libscrypt_SHA256_Init(&ctx->octx);
319 | memset(pad, 0x5c, 64);
320 | for (i = 0; i < Klen; i++)
321 | pad[i] ^= K[i];
322 | libscrypt_SHA256_Update(&ctx->octx, pad, 64);
323 |
324 | /* Clean the stack. */
325 | memset(khash, 0, 32);
326 | }
327 |
328 | /* Add bytes to the HMAC-SHA256 operation. */
329 | void
330 | libscrypt_HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len)
331 | {
332 |
333 | /* Feed data to the inner SHA256 operation. */
334 | libscrypt_SHA256_Update(&ctx->ictx, in, len);
335 | }
336 |
337 | /* Finish an HMAC-SHA256 operation. */
338 | void
339 | libscrypt_HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx)
340 | {
341 | unsigned char ihash[32];
342 |
343 | /* Finish the inner SHA256 operation. */
344 | libscrypt_SHA256_Final(ihash, &ctx->ictx);
345 |
346 | /* Feed the inner hash to the outer SHA256 operation. */
347 | libscrypt_SHA256_Update(&ctx->octx, ihash, 32);
348 |
349 | /* Finish the outer SHA256 operation. */
350 | libscrypt_SHA256_Final(digest, &ctx->octx);
351 |
352 | /* Clean the stack. */
353 | memset(ihash, 0, 32);
354 | }
355 |
356 | /**
357 | * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
358 | * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
359 | * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
360 | */
361 | void
362 | libscrypt_PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
363 | size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
364 | {
365 | HMAC_SHA256_CTX PShctx, hctx;
366 | size_t i;
367 | uint8_t ivec[4];
368 | uint8_t U[32];
369 | uint8_t T[32];
370 | uint64_t j;
371 | int k;
372 | size_t clen;
373 |
374 | /* Compute HMAC state after processing P and S. */
375 | libscrypt_HMAC_SHA256_Init(&PShctx, passwd, passwdlen);
376 | libscrypt_HMAC_SHA256_Update(&PShctx, salt, saltlen);
377 |
378 | /* Iterate through the blocks. */
379 | for (i = 0; i * 32 < dkLen; i++) {
380 | /* Generate INT(i + 1). */
381 | be32enc(ivec, (uint32_t)(i + 1));
382 |
383 | /* Compute U_1 = PRF(P, S || INT(i)). */
384 | memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
385 | libscrypt_HMAC_SHA256_Update(&hctx, ivec, 4);
386 | libscrypt_HMAC_SHA256_Final(U, &hctx);
387 |
388 | /* T_i = U_1 ... */
389 | memcpy(T, U, 32);
390 |
391 | for (j = 2; j <= c; j++) {
392 | /* Compute U_j. */
393 | libscrypt_HMAC_SHA256_Init(&hctx, passwd, passwdlen);
394 | libscrypt_HMAC_SHA256_Update(&hctx, U, 32);
395 | libscrypt_HMAC_SHA256_Final(U, &hctx);
396 |
397 | /* ... xor U_j ... */
398 | for (k = 0; k < 32; k++)
399 | T[k] ^= U[k];
400 | }
401 |
402 | /* Copy as many bytes as necessary into buf. */
403 | clen = dkLen - i * 32;
404 | if (clen > 32)
405 | clen = 32;
406 | memcpy(&buf[i * 32], T, clen);
407 | }
408 |
409 | /* Clean PShctx, since we never called _Final on it. */
410 | memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX));
411 | }
412 |
--------------------------------------------------------------------------------
/libscrypt/sha256.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2005,2007,2009 Colin Percival
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 | * SUCH DAMAGE.
25 | *
26 | * $FreeBSD: src/lib/libmd/sha256.h,v 1.2 2006/01/17 15:35:56 phk Exp $
27 | */
28 |
29 | #ifndef _SHA256_H_
30 | #define _SHA256_H_
31 |
32 | #include
33 |
34 | #include
35 |
36 | typedef struct libscrypt_SHA256Context {
37 | uint32_t state[8];
38 | uint32_t count[2];
39 | unsigned char buf[64];
40 | } SHA256_CTX;
41 |
42 | typedef struct libscrypt_HMAC_SHA256Context {
43 | SHA256_CTX ictx;
44 | SHA256_CTX octx;
45 | } HMAC_SHA256_CTX;
46 |
47 | void libscrypt_SHA256_Init(/*@out@*/ SHA256_CTX *);
48 | void libscrypt_SHA256_Update(SHA256_CTX *, const void *, size_t);
49 |
50 | /* Original declaration:
51 | * void SHA256_Final(unsigned char [32], SHA256_CTX *);
52 | */
53 | void libscrypt_SHA256_Final(/*@out@*/ unsigned char [], SHA256_CTX *);
54 | void libscrypt_HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t);
55 | void libscrypt_HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t);
56 |
57 | /* Original declaration:
58 | * void HMAC_SHA256_Final(unsigned char [32], HMAC_SHA256_CTX *);
59 | */
60 | void libscrypt_HMAC_SHA256_Final(unsigned char [], HMAC_SHA256_CTX *);
61 |
62 | /**
63 | * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
64 | * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
65 | * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
66 | */
67 | void libscrypt_PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,
68 | uint64_t, uint8_t *, size_t);
69 |
70 | #endif /* !_SHA256_H_ */
71 |
--------------------------------------------------------------------------------
/libscrypt/skey.h:
--------------------------------------------------------------------------------
1 | int libscrypt_skey_encode(unsigned char const *src, size_t srclength,
2 | /*@out@*/ char *target, size_t targetsize);
3 |
--------------------------------------------------------------------------------
/libscrypt/slowequals.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | /* Implements a constant time version of strcmp()
4 | * Will return 1 if a and b are equal, 0 if they are not */
5 | int slow_equals(const char* a, const char* b)
6 | {
7 | size_t lena, lenb, diff, i;
8 | lena = strlen(a);
9 | lenb = strlen(b);
10 | diff = strlen(a) ^ strlen(b);
11 |
12 | for(i=0; i we have isn't usable. */
34 | #if !HAVE_DECL_BE64ENC
35 | #undef HAVE_SYS_ENDIAN_H
36 | #endif
37 |
38 | #ifdef HAVE_SYS_ENDIAN_H
39 |
40 | #include
41 |
42 | #else
43 |
44 | #include
45 | #ifdef _MSC_VER
46 | #define INLINE __inline
47 | #else
48 | #define INLINE inline
49 | #endif
50 |
51 | static INLINE uint32_t
52 | be32dec(const void *pp)
53 | {
54 | const uint8_t *p = (uint8_t const *)pp;
55 |
56 | return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
57 | ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
58 | }
59 |
60 | static INLINE void
61 | be32enc(void *pp, uint32_t x)
62 | {
63 | uint8_t * p = (uint8_t *)pp;
64 |
65 | p[3] = x & 0xff;
66 | p[2] = (x >> 8) & 0xff;
67 | p[1] = (x >> 16) & 0xff;
68 | p[0] = (x >> 24) & 0xff;
69 | }
70 |
71 | static INLINE uint64_t
72 | be64dec(const void *pp)
73 | {
74 | const uint8_t *p = (uint8_t const *)pp;
75 |
76 | return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
77 | ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
78 | ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
79 | ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
80 | }
81 |
82 | static INLINE void
83 | be64enc(void *pp, uint64_t x)
84 | {
85 | uint8_t * p = (uint8_t *)pp;
86 |
87 | p[7] = x & 0xff;
88 | p[6] = (x >> 8) & 0xff;
89 | p[5] = (x >> 16) & 0xff;
90 | p[4] = (x >> 24) & 0xff;
91 | p[3] = (x >> 32) & 0xff;
92 | p[2] = (x >> 40) & 0xff;
93 | p[1] = (x >> 48) & 0xff;
94 | p[0] = (x >> 56) & 0xff;
95 | }
96 |
97 | static INLINE uint32_t
98 | le32dec(const void *pp)
99 | {
100 | const uint8_t *p = (uint8_t const *)pp;
101 |
102 | return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
103 | ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
104 | }
105 |
106 | static INLINE void
107 | le32enc(void *pp, uint32_t x)
108 | {
109 | uint8_t * p = (uint8_t *)pp;
110 |
111 | p[0] = x & 0xff;
112 | p[1] = (x >> 8) & 0xff;
113 | p[2] = (x >> 16) & 0xff;
114 | p[3] = (x >> 24) & 0xff;
115 | }
116 |
117 | static INLINE uint64_t
118 | le64dec(const void *pp)
119 | {
120 | const uint8_t *p = (uint8_t const *)pp;
121 |
122 | return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
123 | ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
124 | ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
125 | ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
126 | }
127 |
128 | static INLINE void
129 | le64enc(void *pp, uint64_t x)
130 | {
131 | uint8_t * p = (uint8_t *)pp;
132 |
133 | p[0] = x & 0xff;
134 | p[1] = (x >> 8) & 0xff;
135 | p[2] = (x >> 16) & 0xff;
136 | p[3] = (x >> 24) & 0xff;
137 | p[4] = (x >> 32) & 0xff;
138 | p[5] = (x >> 40) & 0xff;
139 | p[6] = (x >> 48) & 0xff;
140 | p[7] = (x >> 56) & 0xff;
141 | }
142 | #endif /* !HAVE_SYS_ENDIAN_H */
143 |
144 | #endif /* !_SYSENDIAN_H_ */
145 |
--------------------------------------------------------------------------------
/libscrypt/z85.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Stanislav Artemkin .
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are
6 | * met:
7 | *
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above
11 | * copyright notice, this list of conditions and the following disclaimer
12 | * in the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | *
27 | * Implementation of 32/Z85 specification (http://rfc.zeromq.org/spec:32/Z85)
28 | * Source repository: http://github.com/artemkin/z85
29 | */
30 |
31 | #include
32 | #include
33 | #include
34 |
35 | #include "z85.h"
36 |
37 | typedef unsigned int uint32_t;
38 | typedef unsigned char byte;
39 |
40 | // make sure uint32_t is 32-bit
41 | typedef char Z85_uint32_t_static_assert[(sizeof(uint32_t) * CHAR_BIT == 32) * 2 - 1];
42 |
43 | #define DIV85_MAGIC 3233857729ULL
44 | // make sure magic constant is 64-bit
45 | typedef char Z85_div85_magic_static_assert[(sizeof(DIV85_MAGIC) * CHAR_BIT == 64) * 2 - 1];
46 |
47 | #define DIV85(number) ((uint32_t)((DIV85_MAGIC * number) >> 32) >> 6)
48 |
49 | static const char* base85 =
50 | {
51 | "0123456789"
52 | "abcdefghij"
53 | "klmnopqrst"
54 | "uvwxyzABCD"
55 | "EFGHIJKLMN"
56 | "OPQRSTUVWX"
57 | "YZ.-:+=^!/"
58 | "*?&<>()[]{"
59 | "}@%$#"
60 | };
61 |
62 | static byte base256[] =
63 | {
64 | 0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00,
65 | 0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45,
66 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
67 | 0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47,
68 | 0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
69 | 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
70 | 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
71 | 0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00,
72 | 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
73 | 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
74 | 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
75 | 0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00
76 | };
77 |
78 | int libscrypt_z85_encode(src, srclength, target, targsize)
79 | unsigned char const *src;
80 | size_t srclength;
81 | char *target;
82 | size_t targsize;
83 | {
84 | size_t datalength = 0;
85 | memset(target, 0, targsize);
86 |
87 | if (targsize < (Z85_encode_with_padding_bound(srclength) + 1)) {
88 | return (-1); //not enough space for output
89 | }
90 |
91 | //encode the input buffer, padding it if necessary
92 | datalength = Z85_encode_with_padding((const char * )src, target, srclength);
93 | if ( datalength == 0)
94 | return (-1); //something went wrong
95 |
96 | target[datalength] = '\0'; // write null terminating char
97 | return datalength;
98 | }
99 |
100 | int libscrypt_z85_decode(src, target, targsize)
101 | char const *src;
102 | unsigned char *target;
103 | size_t targsize;
104 | {
105 | size_t datalength = 0;
106 | if (targsize < (Z85_decode_with_padding_bound(src, strlen(src)) + 1)) {
107 | return (-1); //not enough space for output
108 | }
109 |
110 | //decode the input buffer, padding it if necessary
111 | datalength = Z85_decode_with_padding(src, (char *) target, strlen(src));
112 | if ( datalength == 0)
113 | return (-1); //something went wrong
114 |
115 | target[datalength] = '\0'; // write null terminating char
116 | return datalength;
117 | }
118 |
119 | char* Z85_encode_unsafe(const char* source, const char* sourceEnd, char* dest)
120 | {
121 | byte* src = (byte*)source;
122 | byte* end = (byte*)sourceEnd;
123 | byte* dst = (byte*)dest;
124 | uint32_t value;
125 | uint32_t value2;
126 |
127 | for (; src != end; src += 4, dst += 5)
128 | {
129 | // unpack big-endian frame
130 | value = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
131 |
132 | value2 = DIV85(value); dst[4] = base85[value - value2 * 85]; value = value2;
133 | value2 = DIV85(value); dst[3] = base85[value - value2 * 85]; value = value2;
134 | value2 = DIV85(value); dst[2] = base85[value - value2 * 85]; value = value2;
135 | value2 = DIV85(value); dst[1] = base85[value - value2 * 85];
136 | dst[0] = base85[value2];
137 | }
138 |
139 | return (char*)dst;
140 | }
141 |
142 | char* Z85_decode_unsafe(const char* source, const char* sourceEnd, char* dest)
143 | {
144 | byte* src = (byte*)source;
145 | byte* end = (byte*)sourceEnd;
146 | byte* dst = (byte*)dest;
147 | uint32_t value;
148 |
149 | for (; src != end; src += 5, dst += 4)
150 | {
151 | value = base256[(src[0] - 32) & 127];
152 | value = value * 85 + base256[(src[1] - 32) & 127];
153 | value = value * 85 + base256[(src[2] - 32) & 127];
154 | value = value * 85 + base256[(src[3] - 32) & 127];
155 | value = value * 85 + base256[(src[4] - 32) & 127];
156 |
157 | // pack big-endian frame
158 | dst[0] = value >> 24;
159 | dst[1] = (byte)(value >> 16);
160 | dst[2] = (byte)(value >> 8);
161 | dst[3] = (byte)(value);
162 | }
163 |
164 | return (char*)dst;
165 | }
166 |
167 | size_t Z85_encode_bound(size_t size)
168 | {
169 | return size * 5 / 4;
170 | }
171 |
172 | size_t Z85_decode_bound(size_t size)
173 | {
174 | return size * 4 / 5;
175 | }
176 |
177 | size_t Z85_encode(const char* source, char* dest, size_t inputSize)
178 | {
179 | if (!source || !dest || inputSize % 4)
180 | {
181 | assert(!"wrong source, destination or input size");
182 | return 0;
183 | }
184 |
185 | return Z85_encode_unsafe(source, source + inputSize, dest) - dest;
186 | }
187 |
188 | size_t Z85_decode(const char* source, char* dest, size_t inputSize)
189 | {
190 | if (!source || !dest || inputSize % 5)
191 | {
192 | assert(!"wrong source, destination or input size");
193 | return 0;
194 | }
195 |
196 | return Z85_decode_unsafe(source, source + inputSize, dest) - dest;
197 | }
198 |
199 | size_t Z85_encode_with_padding_bound(size_t size)
200 | {
201 | if (size == 0) return 0;
202 | size = Z85_encode_bound(size);
203 | return size + (5 - size % 5) % 5 + 1;
204 | }
205 |
206 | size_t Z85_decode_with_padding_bound(const char* source, size_t size)
207 | {
208 | if (size == 0 || !source || (byte)(source[0] - '0' - 1) > 3) return 0;
209 | return Z85_decode_bound(size - 1) - 4 + (source[0] - '0');
210 | }
211 |
212 | size_t Z85_encode_with_padding(const char* source, char* dest, size_t inputSize)
213 | {
214 | size_t tailBytes = inputSize % 4;
215 | char tailBuf[4] = { 0 };
216 | char* dst = dest;
217 | const char* end = source + inputSize - tailBytes;
218 |
219 | assert(source && dest);
220 |
221 | // zero length string is not padded
222 | if (!source || !dest || inputSize == 0)
223 | {
224 | return 0;
225 | }
226 |
227 | (dst++)[0] = (tailBytes == 0 ? '4' : '0' + (char)tailBytes); // write tail bytes count
228 | dst = Z85_encode_unsafe(source, end, dst); // write body
229 |
230 | // write tail
231 | switch (tailBytes)
232 | {
233 | case 3:
234 | tailBuf[2] = end[2];
235 | case 2:
236 | tailBuf[1] = end[1];
237 | case 1:
238 | tailBuf[0] = end[0];
239 | dst = Z85_encode_unsafe(tailBuf, tailBuf + 4, dst);
240 | }
241 |
242 | return dst - dest;
243 | }
244 |
245 | size_t Z85_decode_with_padding(const char* source, char* dest, size_t inputSize)
246 | {
247 | char* dst = dest;
248 | size_t tailBytes;
249 | char tailBuf[4] = { 0 };
250 | const char* end = source + inputSize;
251 |
252 | assert(source && dest && (inputSize == 0 || (inputSize - 1) % 5 == 0));
253 |
254 | // zero length string is not padded
255 | if (!source || !dest || inputSize == 0 || (inputSize - 1) % 5)
256 | {
257 | return 0;
258 | }
259 |
260 | tailBytes = (source++)[0] - '0'; // possible values: 1, 2, 3 or 4
261 | if (tailBytes - 1 > 3)
262 | {
263 | assert(!"wrong tail bytes count");
264 | return 0;
265 | }
266 |
267 | end -= 5;
268 | if (source != end)
269 | {
270 | // decode body
271 | dst = Z85_decode_unsafe(source, end, dst);
272 | }
273 |
274 | // decode last 5 bytes chunk
275 | Z85_decode_unsafe(end, end + 5, tailBuf);
276 |
277 | switch (tailBytes)
278 | {
279 | case 4:
280 | dst[3] = tailBuf[3];
281 | case 3:
282 | dst[2] = tailBuf[2];
283 | case 2:
284 | dst[1] = tailBuf[1];
285 | case 1:
286 | dst[0] = tailBuf[0];
287 | }
288 |
289 | return dst - dest + tailBytes;
290 | }
291 |
--------------------------------------------------------------------------------
/libscrypt/z85.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Stanislav Artemkin .
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are
6 | * met:
7 | *
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above
11 | * copyright notice, this list of conditions and the following disclaimer
12 | * in the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | *
27 | * Implementation of 32/Z85 specification (http://rfc.zeromq.org/spec:32/Z85)
28 | * Source repository: http://github.com/artemkin/z85
29 | */
30 |
31 | #pragma once
32 |
33 | #include
34 |
35 | #if defined (__cplusplus)
36 | extern "C" {
37 | #endif
38 |
39 | /*******************************************************************************
40 | * libscrypt wrappers *
41 | *******************************************************************************/
42 | int libscrypt_z85_encode(unsigned char const *src, size_t srclength,
43 | /*@out@*/ char *target, size_t targetsize);
44 | int libscrypt_z85_decode(char const *src,
45 | /*@out@*/ unsigned char *target, size_t targetsize);
46 |
47 | /*******************************************************************************
48 | * ZeroMQ Base-85 encoding/decoding functions with custom padding *
49 | *******************************************************************************/
50 |
51 | /**
52 | * @brief Encodes 'inputSize' bytes from 'source' into 'dest'.
53 | * If 'inputSize' is not divisible by 4 with no remainder, 'source' is padded.
54 | * Destination buffer must be already allocated. Use Z85_encode_with_padding_bound() to
55 | * evaluate size of the destination buffer.
56 | *
57 | * @param source in, input buffer (binary string to be encoded)
58 | * @param dest out, destination buffer
59 | * @param inputSize in, number of bytes to be encoded
60 | * @return number of printable symbols written into 'dest' or 0 if something goes wrong
61 | */
62 | size_t Z85_encode_with_padding(const char* source, char* dest, size_t inputSize);
63 |
64 | /**
65 | * @brief Decodes 'inputSize' printable symbols from 'source' into 'dest',
66 | * encoded with Z85_encode_with_padding().
67 | * Destination buffer must be already allocated. Use Z85_decode_with_padding_bound() to
68 | * evaluate size of the destination buffer.
69 | *
70 | * @param source in, input buffer (printable string to be decoded)
71 | * @param dest out, destination buffer
72 | * @param inputSize in, number of symbols to be decoded
73 | * @return number of bytes written into 'dest' or 0 if something goes wrong
74 | */
75 | size_t Z85_decode_with_padding(const char* source, char* dest, size_t inputSize);
76 |
77 | /**
78 | * @brief Evaluates a size of output buffer needed to encode 'size' bytes
79 | * into string of printable symbols using Z85_encode_with_padding().
80 | *
81 | * @param size in, number of bytes to be encoded
82 | * @return minimal size of output buffer in bytes
83 | */
84 | size_t Z85_encode_with_padding_bound(size_t size);
85 |
86 | /**
87 | * @brief Evaluates a size of output buffer needed to decode 'size' symbols
88 | * into binary string using Z85_decode_with_padding().
89 | *
90 | * @param source in, input buffer (first symbol is read from 'source' to evaluate padding)
91 | * @param size in, number of symbols to be decoded
92 | * @return minimal size of output buffer in bytes
93 | */
94 | size_t Z85_decode_with_padding_bound(const char* source, size_t size);
95 |
96 |
97 |
98 | /*******************************************************************************
99 | * ZeroMQ Base-85 encoding/decoding functions (specification compliant) *
100 | *******************************************************************************/
101 |
102 | /**
103 | * @brief Encodes 'inputSize' bytes from 'source' into 'dest'.
104 | * If 'inputSize' is not divisible by 4 with no remainder, 0 is retured.
105 | * Destination buffer must be already allocated. Use Z85_encode_bound() to
106 | * evaluate size of the destination buffer.
107 | *
108 | * @param source in, input buffer (binary string to be encoded)
109 | * @param dest out, destination buffer
110 | * @param inputSize in, number of bytes to be encoded
111 | * @return number of printable symbols written into 'dest' or 0 if something goes wrong
112 | */
113 | size_t Z85_encode(const char* source, char* dest, size_t inputSize);
114 |
115 | /**
116 | * @brief Decodes 'inputSize' printable symbols from 'source' into 'dest'.
117 | * If 'inputSize' is not divisible by 5 with no remainder, 0 is returned.
118 | * Destination buffer must be already allocated. Use Z85_decode_bound() to
119 | * evaluate size of the destination buffer.
120 | *
121 | * @param source in, input buffer (printable string to be decoded)
122 | * @param dest out, destination buffer
123 | * @param inputSize in, number of symbols to be decoded
124 | * @return number of bytes written into 'dest' or 0 if something goes wrong
125 | */
126 | size_t Z85_decode(const char* source, char* dest, size_t inputSize);
127 |
128 | /**
129 | * @brief Evaluates a size of output buffer needed to encode 'size' bytes
130 | * into string of printable symbols using Z85_encode().
131 | *
132 | * @param size in, number of bytes to be encoded
133 | * @return minimal size of output buffer in bytes
134 | */
135 | size_t Z85_encode_bound(size_t size);
136 |
137 | /**
138 | * @brief Evaluates a size of output buffer needed to decode 'size' symbols
139 | * into binary string using Z85_decode().
140 | *
141 | * @param size in, number of symbols to be decoded
142 | * @return minimal size of output buffer in bytes
143 | */
144 | size_t Z85_decode_bound(size_t size);
145 |
146 |
147 |
148 | /*******************************************************************************
149 | * ZeroMQ Base-85 unsafe encoding/decoding functions (specification compliant) *
150 | *******************************************************************************/
151 |
152 | /**
153 | * @brief Encodes bytes from [source;sourceEnd) range into 'dest'.
154 | * It can be used for implementation of your own padding scheme.
155 | * Preconditions:
156 | * - (sourceEnd - source) % 4 == 0
157 | * - destination buffer must be already allocated
158 | *
159 | * @param source in, begin of input buffer
160 | * @param sourceEnd in, end of input buffer (not included)
161 | * @param dest out, output buffer
162 | * @return a pointer immediately after last symbol written into the 'dest'
163 | */
164 | char* Z85_encode_unsafe(const char* source, const char* sourceEnd, char* dest);
165 |
166 | /**
167 | * @brief Decodes symbols from [source;sourceEnd) range into 'dest'.
168 | * It can be used for implementation of your own padding scheme.
169 | * Preconditions:
170 | * - (sourceEnd - source) % 5 == 0
171 | * - destination buffer must be already allocated
172 | *
173 | * @param source in, begin of input buffer
174 | * @param sourceEnd in, end of input buffer (not included)
175 | * @param dest out, output buffer
176 | * @return a pointer immediately after last byte written into the 'dest'
177 | */
178 | char* Z85_decode_unsafe(const char* source, const char* sourceEnd, char* dest);
179 |
180 | #if defined (__cplusplus)
181 | }
182 | #endif
183 |
184 |
--------------------------------------------------------------------------------
/man/genpass.1:
--------------------------------------------------------------------------------
1 | .TH GENPASS "1" "January 2016" "genpass 2016.01.01" "User Commands"
2 | .SH NAME
3 | genpass \- A stateless password generator.
4 | .SH SYNOPSIS
5 | .B genpass
6 | [\fIoption\fR]... [\fIsite\fR]
7 | .SH DESCRIPTION
8 | Generate stateless passwords based on a two level hash scheme.
9 | .TP
10 | \fB\-n\fR, \fB\-\-name\fR "Full Name"
11 | name
12 | .TP
13 | \fB\-p\fR, \fB\-\-password\fR "Secret"
14 | master password
15 | .TP
16 | \fB\-s\fR, \fB\-\-site\fR "site.tld"
17 | site login
18 | .TP
19 | \fB\-r\fR, \fB\-\-registration\-mode\fR
20 | ask twice for master password
21 | .TP
22 | \fB\-f\fR, \fB\-\-file\fR FILE
23 | use|write cache key from|to FILE
24 | .TP
25 | \fB\-l\fR, \fB\-\-key\-length\fR 8\-1024
26 | key length in bytes, "32" by default
27 | .TP
28 | \fB\-C\fR, \fB\-\-cache\-cost\fR 1\-30
29 | cpu/memory cost for cache key, "20" by default
30 | .TP
31 | \fB\-c\fR, \fB\-\-cost\fR 1\-30
32 | cpu/memory cost for final key, "10" by default
33 | .TP
34 | \fB\-\-scrypt\-r\fR 1\-9999
35 | block size, "8" by default (advanced)
36 | .TP
37 | \fB\-\-scrypt\-p\fR 1\-99999
38 | parallelization, "16" by default (advanced)
39 | .TP
40 | \fB\-\-config\fR FILE
41 | read configuration from FILE
42 | .TP
43 | \fB\-N\fR, \fB\-\-dry\-run\fR
44 | perform a trial run with no changes made
45 | .TP
46 | \fB\-e\fR, \fB\-\-encoding\fR ENCODING
47 | password encoding output, "z85" by default.
48 | .PP
49 | ENCODING: dec|hex|base64|z85|skey
50 | .TP
51 | \fB\-1\fR, \fB\-\-single\fR
52 | use single function derivation
53 | .TP
54 | \fB\-v\fR, \fB\-\-verbose\fR
55 | verbose mode
56 | .TP
57 | \fB\-V\fR, \fB\-\-version\fR
58 | show version and exit
59 | .TP
60 | \fB\-h\fR, \fB\-\-help\fR
61 | show this help message and exit
62 | .SH "REPORTING BUGS"
63 | Report genpass bugs in
64 | .br
65 | .SH "SEE ALSO"
66 | Password Multiplier using iterated sha1 hashing, 2005.
67 | .br
68 | Stronger Key Derivation Via Sequential Memory-hard Functions, 2009.
69 | .PP
70 | getpass(1)
71 |
--------------------------------------------------------------------------------
/man/getpass.1:
--------------------------------------------------------------------------------
1 | .TH GETPASS "1" "January 2016" "getpass 2016.01.01" "User Commands"
2 | .SH NAME
3 | getpass \- A wrapper around genpass, a stateless password generator.
4 | .SH SYNOPSIS
5 | .B getpass
6 | [\fIoption\fR]... \fIsite\fR
7 | .SH DESCRIPTION
8 | Generate stateless passwords based on a two level hash scheme. Environment lookup, system clipboard integration and graphical support.
9 | .TP
10 | \fB\-n\fR, \fB\-\-name\fR "Full Name"
11 | name
12 | .TP
13 | \fB\-p\fR, \fB\-\-password\fR "Secret"
14 | master password
15 | .TP
16 | \fB\-r\fR, \fB\-\-registration\-mode\fR
17 | ask twice for master password
18 | .TP
19 | \fB\-f\fR, \fB\-\-file\fR FILE
20 | use|write cache key from|to FILE
21 | .TP
22 | \fB\-l\fR, \fB\-\-key\-length\fR 8\-1024
23 | key length in bytes, "32" by default
24 | .TP
25 | \fB\-C\fR, \fB\-\-cache\-cost\fR 1\-30
26 | cpu/memory cost for cache key, "20" by default
27 | .TP
28 | \fB\-c\fR, \fB\-\-cost\fR 1\-30
29 | cpu/memory cost for final key, "10" by default
30 | .TP
31 | \fB\-\-scrypt\-r\fR 1\-9999
32 | block size, "8" by default (advanced)
33 | .TP
34 | \fB\-\-scrypt\-p\fR 1\-99999
35 | parallelization, "16" by default (advanced)
36 | .TP
37 | \fB\-\-config\fR FILE
38 | read configuration from FILE
39 | .TP
40 | \fB\-N\fR, \fB\-\-dry\-run\fR
41 | perform a trial run with no changes made
42 | .TP
43 | \fB\-e\fR, \fB\-\-encoding\fR ENCODING
44 | password encoding output, "z85" by default.
45 | .PP
46 | ENCODING: dec|hex|base64|z85|skey
47 | .TP
48 | \fB\-1\fR, \fB\-\-single\fR
49 | use single function derivation
50 | .TP
51 | \fB\-k\fR, \fB\-\-kill-after\fR SEC
52 | kill clipboard after N seconds, "10" by default, 0 to disable
53 | .TP
54 | \fB\-v\fR, \fB\-\-verbose\fR
55 | verbose mode
56 | .TP
57 | \fB\-V\fR, \fB\-\-version\fR
58 | show version and exit
59 | .TP
60 | \fB\-h\fR, \fB\-\-help\fR
61 | show this help message and exit
62 | .SH "REPORTING BUGS"
63 | Report getpass bugs in
64 | .br
65 | .SH "SEE ALSO"
66 | Password Multiplier using iterated sha1 hashing, 2005.
67 | .br
68 | Stronger Key Derivation Via Sequential Memory-hard Functions, 2009.
69 | .PP
70 | genpass(1)
71 |
--------------------------------------------------------------------------------
/poison/poison.h:
--------------------------------------------------------------------------------
1 | /*
2 | poison.h - header to ban unsafe C/C++ functions from applications, modified
3 | License: public domain
4 |
5 | Original: https://github.com/leafsr/gcc-poison, version 04.12.2013
6 | Post about it: http://blog.leafsr.com/2013/12/02/gcc-poison
7 | Copyright 2013 - Leaf Security Research
8 | */
9 |
10 | //macro guard used to avoid the problem of double inclusion
11 | #ifndef __POISON_H__
12 | #define __POISON_H__
13 | #ifdef __GNUC__
14 |
15 | /* string handling functions */
16 | # pragma GCC poison strcpy wcscpy stpcpy wcpcpy
17 | # pragma GCC poison scanf sscanf vscanf fwscanf swscanf wscanf
18 | # pragma GCC poison gets puts
19 | # pragma GCC poison strcat wcscat
20 | # pragma GCC poison wcrtomb wctob
21 | # pragma GCC poison sprintf vsprintf vfprintf
22 | # pragma GCC poison asprintf vasprintf
23 | # pragma GCC poison strncpy wcsncpy
24 | # pragma GCC poison strtok wcstok
25 | # pragma GCC poison strdupa strndupa
26 |
27 | /* signal related */
28 | # pragma GCC poison longjmp siglongjmp
29 | # pragma GCC poison setjmp sigsetjmp
30 |
31 | /* memory allocation */
32 | ///next line is commented because it produces "warning: poisoning existing macro "alloca"
33 | //[enabledby default]" after including some system header
34 | //# pragma GCC poison alloca
35 | # pragma GCC poison mallopt
36 |
37 | /* file API */
38 | # pragma GCC poison remove
39 | # pragma GCC poison mktemp tmpnam tempnam
40 | # pragma GCC poison getwd
41 |
42 | /* misc */
43 | # pragma GCC poison getlogin getpass cuserid
44 | # pragma GCC poison rexec rexec_af
45 |
46 | /* command and program execution */
47 | //use of that functions is often insecure and unjustified
48 | //system() call is used in cpwd so it was remowed from line below
49 | # pragma GCC poison exec execl execlp execle execv execvp execvpe execve fexecve
50 |
51 | /* deprecated network functions */
52 | # pragma GCC poison gethostbyname gethostbyaddr inet_ntoa inet_aton
53 |
54 | #endif
55 | #endif
56 |
--------------------------------------------------------------------------------
/readpass/Makefile:
--------------------------------------------------------------------------------
1 | CC?=gcc
2 | CFLAGS?=-O2 -Wall -g
3 |
4 | all:
5 | $(CC) -I. -c -o readpass.o readpass.c
6 |
7 | clean:
8 | rm -f *.o
9 |
--------------------------------------------------------------------------------
/readpass/readpass.c:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2009 Colin Percival
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 | * SUCH DAMAGE.
25 | */
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #include "warn.h"
34 | #include "readpass.h"
35 |
36 | #define MAXPASSLEN 2048
37 | #define MAXINPUTLEN 2048
38 |
39 | /**
40 | * tarsnap_readpass(passwd, prompt, confirmprompt, devtty)
41 | * If ${devtty} is non-zero, read a password from /dev/tty if possible; if
42 | * not, read from stdin. If reading from a tty (either /dev/tty or stdin),
43 | * disable echo and prompt the user by printing ${prompt} to stderr. If
44 | * ${confirmprompt} is non-NULL, read a second password (prompting if a
45 | * terminal is being used) and repeat until the user enters the same password
46 | * twice. Return the password as a malloced NUL-terminated string via
47 | * ${passwd}. The obscure name is to avoid namespace collisions due to the
48 | * getpass / readpass / readpassphrase / etc. functions in various libraries.
49 | */
50 | int
51 | tarsnap_readpass(char ** passwd, const char * prompt,
52 | const char * confirmprompt, int devtty)
53 | {
54 | FILE * readfrom;
55 | char passbuf[MAXPASSLEN];
56 | char confpassbuf[MAXPASSLEN];
57 | struct termios term, term_old;
58 | int usingtty;
59 |
60 | /*
61 | * If devtty != 0, try to open /dev/tty; if that fails, or if devtty
62 | * is zero, we'll read the password from stdin instead.
63 | */
64 | if ((devtty == 0) || ((readfrom = fopen("/dev/tty", "r")) == NULL))
65 | readfrom = stdin;
66 |
67 | /* If we're reading from a terminal, try to disable echo. */
68 | if ((usingtty = isatty(fileno(readfrom))) != 0) {
69 | if (tcgetattr(fileno(readfrom), &term_old)) {
70 | warn("Cannot read terminal settings");
71 | goto err1;
72 | }
73 | memcpy(&term, &term_old, sizeof(struct termios));
74 | term.c_lflag = (term.c_lflag & ~ECHO) | ECHONL;
75 | if (tcsetattr(fileno(readfrom), TCSANOW, &term)) {
76 | warn("Cannot set terminal settings");
77 | goto err1;
78 | }
79 | }
80 |
81 | retry:
82 | /* If we have a terminal, prompt the user to enter the password. */
83 | if (usingtty)
84 | fprintf(stderr, "%s: ", prompt);
85 |
86 | /* Read the password. */
87 | if (fgets(passbuf, MAXPASSLEN, readfrom) == NULL) {
88 | warn("Cannot read password");
89 | goto err2;
90 | }
91 |
92 | /* Confirm the password if necessary. */
93 | if (confirmprompt != NULL) {
94 | if (usingtty)
95 | fprintf(stderr, "%s: ", confirmprompt);
96 | if (fgets(confpassbuf, MAXPASSLEN, readfrom) == NULL) {
97 | warn("Cannot read password");
98 | goto err2;
99 | }
100 | if (strcmp(passbuf, confpassbuf)) {
101 | fprintf(stderr,
102 | "Passwords mismatch, please try again\n");
103 | goto retry;
104 | }
105 | }
106 |
107 | /* Terminate the string at the first "\r" or "\n" (if any). */
108 | passbuf[strcspn(passbuf, "\r\n")] = '\0';
109 |
110 | /* If we changed terminal settings, reset them. */
111 | if (usingtty)
112 | tcsetattr(fileno(readfrom), TCSANOW, &term_old);
113 |
114 | /* Close /dev/tty if we opened it. */
115 | if (readfrom != stdin)
116 | fclose(readfrom);
117 |
118 | /* Copy the password out. */
119 | if ((*passwd = strdup(passbuf)) == NULL) {
120 | warn("Cannot allocate memory");
121 | goto err1;
122 | }
123 |
124 | /* Zero any stored passwords. */
125 | memset(passbuf, 0, MAXPASSLEN);
126 | memset(confpassbuf, 0, MAXPASSLEN);
127 |
128 | /* Success! */
129 | return (0);
130 |
131 | err2:
132 | /* Reset terminal settings if necessary. */
133 | if (usingtty)
134 | tcsetattr(fileno(readfrom), TCSAFLUSH, &term_old);
135 | err1:
136 | /* Close /dev/tty if we opened it. */
137 | if (readfrom != stdin)
138 | fclose(readfrom);
139 |
140 | /* Failure! */
141 | return (-1);
142 | }
143 |
144 | //use termio settings as a workaround to flush stdin
145 | int
146 | tarsnap_readinput(char ** input, const char * prompt,
147 | const char * confirmprompt, int devtty)
148 | {
149 | FILE * readfrom;
150 | char inputbuf[MAXINPUTLEN];
151 | char confinputbuf[MAXINPUTLEN];
152 | struct termios term, term_old;
153 | int usingtty;
154 |
155 | /*
156 | * If devtty != 0, try to open /dev/tty; if that fails, or if devtty
157 | * is zero, we'll read entries from stdin instead.
158 | */
159 | if ((devtty == 0) || ((readfrom = fopen("/dev/tty", "r")) == NULL))
160 | readfrom = stdin;
161 |
162 | /* If we're reading from a terminal, try to disable echo. */
163 | if ((usingtty = isatty(fileno(readfrom))) != 0) {
164 | if (tcgetattr(fileno(readfrom), &term_old)) {
165 | warn("Cannot read terminal settings");
166 | goto err1;
167 | }
168 | memcpy(&term, &term_old, sizeof(struct termios));
169 | term.c_lflag = (term.c_lflag & ~ECHO) | ECHONL;
170 | if (tcsetattr(fileno(readfrom), TCSANOW, &term)) {
171 | warn("Cannot set terminal settings");
172 | goto err1;
173 | }
174 | }
175 |
176 | /* use termio settings as a workaround to flush stdin */
177 | /* If we changed terminal settings, reset them. */
178 | if (usingtty)
179 | tcsetattr(fileno(readfrom), TCSANOW, &term_old);
180 | retry:
181 | /* If we have a terminal, prompt the user to enter the input. */
182 | if (usingtty)
183 | fprintf(stderr, "%s: ", prompt);
184 |
185 | /* Read the input. */
186 | if (fgets(inputbuf, MAXINPUTLEN, readfrom) == NULL) {
187 | warn("Cannot read input");
188 | goto err2;
189 | }
190 |
191 | /* Confirm the input if necessary. */
192 | if (confirmprompt != NULL) {
193 | if (usingtty)
194 | fprintf(stderr, "%s: ", confirmprompt);
195 | if (fgets(confinputbuf, MAXINPUTLEN, readfrom) == NULL) {
196 | warn("Cannot read input");
197 | goto err2;
198 | }
199 | if (strcmp(inputbuf, confinputbuf)) {
200 | fprintf(stderr, "Input mismatch, please try again\n");
201 | goto retry;
202 | }
203 | }
204 |
205 | /* Terminate the string at the first "\r" or "\n" (if any). */
206 | inputbuf[strcspn(inputbuf, "\r\n")] = '\0';
207 |
208 | /* Close /dev/tty if we opened it. */
209 | if (readfrom != stdin)
210 | fclose(readfrom);
211 |
212 | /* Copy the input out. */
213 | if ((*input = strdup(inputbuf)) == NULL) {
214 | warn("Cannot allocate memory");
215 | goto err1;
216 | }
217 |
218 | /* Zero any stored input. */
219 | memset(inputbuf, 0, MAXINPUTLEN);
220 | memset(confinputbuf, 0, MAXINPUTLEN);
221 |
222 | /* Success! */
223 | return (0);
224 |
225 | err2:
226 | /* Reset terminal settings if necessary. */
227 | if (usingtty)
228 | tcsetattr(fileno(readfrom), TCSAFLUSH, &term_old);
229 | err1:
230 | /* Close /dev/tty if we opened it. */
231 | if (readfrom != stdin)
232 | fclose(readfrom);
233 |
234 | /* Failure! */
235 | return (-1);
236 | }
237 |
--------------------------------------------------------------------------------
/readpass/readpass.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2009 Colin Percival
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 | * SUCH DAMAGE.
25 | *
26 | * This file was originally written by Colin Percival as part of the Tarsnap
27 | * online backup system.
28 | */
29 | #ifndef _READPASS_H_
30 | #define _READPASS_H_
31 |
32 | /**
33 | * tarsnap_getpass(passwd, prompt, confirmprompt, devtty)
34 | * If ${devtty} is non-zero, read a password from /dev/tty if possible; if
35 | * not, read from stdin. If reading from a tty (either /dev/tty or stdin),
36 | * disable echo and prompt the user by printing ${prompt} to stderr. If
37 | * ${confirmprompt} is non-NULL, read a second password (prompting if a
38 | * terminal is being used) and repeat until the user enters the same password
39 | * twice. Return the password as a malloced NUL-terminated string via
40 | * ${passwd}. The obscure name is to avoid namespace collisions due to the
41 | * getpass / readpass / readpassphrase / etc. functions in various libraries.
42 | */
43 | int tarsnap_readpass (char **, const char *, const char *, int);
44 | int tarsnap_readinput(char **, const char *, const char *, int);
45 |
46 | #endif /* !_READPASS_H_ */
47 |
--------------------------------------------------------------------------------
/readpass/warn.c:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2009 Colin Percival
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 | * SUCH DAMAGE.
25 | *
26 | * This file was originally written by Colin Percival as part of the Tarsnap
27 | * online backup system.
28 | */
29 | //#include "scrypt_platform.h"
30 |
31 | #ifdef HAVE_ERR_H
32 | /*
33 | * Everything is provided through err.h and the associated library, so we
34 | * don't need to do anything here.
35 | */
36 | #else
37 | #include
38 | #include
39 | #include
40 | #include
41 |
42 | #include "warn.h"
43 |
44 | const char * warn_progname = "(null)";
45 |
46 | void
47 | warn(const char * fmt, ...)
48 | {
49 | va_list ap;
50 |
51 | va_start(ap, fmt);
52 | fprintf(stderr, "%s", warn_progname);
53 | if (fmt != NULL) {
54 | fprintf(stderr, ": ");
55 | vfprintf(stderr, fmt, ap);
56 | }
57 | fprintf(stderr, ": %s\n", strerror(errno));
58 | va_end(ap);
59 | }
60 |
61 | void
62 | warnx(const char * fmt, ...)
63 | {
64 | va_list ap;
65 |
66 | va_start(ap, fmt);
67 | fprintf(stderr, "%s", warn_progname);
68 | if (fmt != NULL) {
69 | fprintf(stderr, ": ");
70 | vfprintf(stderr, fmt, ap);
71 | }
72 | fprintf(stderr, "\n");
73 | va_end(ap);
74 | }
75 | #endif
76 |
--------------------------------------------------------------------------------
/readpass/warn.h:
--------------------------------------------------------------------------------
1 | #ifndef _WARN_H_
2 | #define _WARN_H_
3 |
4 | #ifdef HAVE_ERR_H
5 | #include
6 | #else
7 | #define NEED_WARN_PROGNAME
8 | const char * warn_progname;
9 | void warn(const char *, ...);
10 | void warnx(const char *, ...);
11 | #endif
12 |
13 | #endif /* !_WARN_H_ */
14 |
--------------------------------------------------------------------------------
/test/README.md:
--------------------------------------------------------------------------------
1 | Usage
2 | -----
3 |
4 | ```sh
5 | $ xvfb-run sh test.sh
6 | ```
7 |
--------------------------------------------------------------------------------
/test/genpass-mp-input.exp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | rm -rf /tmp/genpass-*.exp
4 | CURRENT_DIR="$(cd "$(dirname "${0}" )" && pwd)"
5 | PATH="${CURRENT_DIR}/../:${PATH}"; export PATH
6 |
7 | expect_script='
8 | log_user 0
9 | spawn genpass-static -f key -C1 -c1 -n1 1
10 |
11 | set timeout 1
12 |
13 | expect { "Master password:" {
14 | send "1"
15 | expect {
16 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!"
17 | }}
18 |
19 | timeout {
20 | puts "genpass failed";
21 | exit 1
22 | }
23 | }'
24 |
25 | printf "%s\\n" "${expect_script}" > /tmp/genpass-mp-input.exp
26 | expect /tmp/genpass-mp-input.exp
27 |
--------------------------------------------------------------------------------
/test/genpass-name-and-mp-input.exp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | rm -rf /tmp/genpass-*.exp
4 | CURRENT_DIR="$(cd "$(dirname "${0}" )" && pwd)"
5 | PATH="${CURRENT_DIR}/../:${PATH}"; export PATH
6 |
7 | expect_script='
8 | log_user 0
9 | spawn genpass-static -f key -C1 -c1 1
10 |
11 | set timeout 1
12 |
13 | expect {
14 | "Name:" {
15 | send "1"
16 | expect {
17 | "Master password:" {
18 | send "1"
19 | expect {
20 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!"
21 | }}}}
22 |
23 | timeout {
24 | puts "genpass failed";
25 | exit 1
26 | }
27 | }'
28 |
29 | printf "%s\\n" "${expect_script}" > /tmp/genpass-name-and-mp-input.exp
30 | expect /tmp/genpass-name-and-mp-input.exp
31 |
--------------------------------------------------------------------------------
/test/genpass-normal-input.exp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | rm -rf /tmp/genpass-*.exp
4 | CURRENT_DIR="$(cd "$(dirname "${0}" )" && pwd)"
5 | PATH="${CURRENT_DIR}/../:${PATH}"; export PATH
6 |
7 | expect_script='
8 | log_user 0
9 | spawn genpass-static -f key -C1 -c1
10 |
11 | set timeout 1
12 |
13 | expect {
14 | "Name:" {
15 | send "1"
16 | expect {
17 | "Site:" {
18 | send "1"
19 | expect {
20 | "Master password:" {
21 | send "1"
22 | expect {
23 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!"
24 | }}}}}}
25 |
26 | timeout {
27 | puts "genpass failed";
28 | exit 1
29 | }
30 | }'
31 |
32 | printf "%s\\n" "${expect_script}" > /tmp/genpass-normal-input.exp
33 | expect /tmp/genpass-normal-input.exp
34 |
--------------------------------------------------------------------------------
/test/genpass-registration-mode.exp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | rm -rf /tmp/genpass-*.exp
4 | CURRENT_DIR="$(cd "$(dirname "${0}" )" && pwd)"
5 | PATH="${CURRENT_DIR}/../:${PATH}"; export PATH
6 |
7 | expect_script='
8 | log_user 0
9 | spawn genpass-static -f key -C1 -c1 --registration-mode
10 |
11 | set timeout 1
12 |
13 | expect {
14 | "Name:" {
15 | send "1"
16 | expect {
17 | "Site:" {
18 | send "1"
19 | expect {
20 | "Master password:" {
21 | send "1"
22 | expect {
23 | "repeat again:" {
24 | send "1"
25 | expect {
26 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!"
27 | }}}}}}}}
28 |
29 | timeout {
30 | puts "genpass failed";
31 | exit 1
32 | }
33 | }'
34 |
35 | printf "%s\\n" "${expect_script}" > /tmp/genpass-registration-mode.exp
36 | expect /tmp/genpass-registration-mode.exp
37 |
38 | expect_script='
39 | log_user 0
40 | spawn genpass-static -f key -C1 -c1 --registration-mode
41 |
42 | set timeout 1
43 |
44 | expect {
45 | "Name:" {
46 | send "1"
47 | expect {
48 | "Site:" {
49 | send "1"
50 | expect {
51 | "Master password:" {
52 | send "1"
53 | expect {
54 | "repeat again:" {
55 | send "2"
56 | expect {
57 | "Master password:" {
58 | send "1"
59 | expect {
60 | "repeat again:" {
61 | send "1"
62 | expect {
63 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!"
64 | }}}}}}}}}}}}
65 |
66 | timeout {
67 | puts "genpass failed";
68 | exit 1
69 | }
70 | }'
71 |
72 | printf "%s\\n" "${expect_script}" > /tmp/genpass-registration-mode.exp
73 | expect /tmp/genpass-registration-mode.exp
74 |
--------------------------------------------------------------------------------
/test/genpass-site-and-mp-input.exp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | rm -rf /tmp/genpass-*.exp
4 | CURRENT_DIR="$(cd "$(dirname "${0}" )" && pwd)"
5 | PATH="${CURRENT_DIR}/../:${PATH}"; export PATH
6 |
7 | expect_script='
8 | log_user 0
9 | spawn genpass-static -f key -C1 -c1 -n1
10 |
11 | set timeout 1
12 |
13 | expect {
14 | "Site:" {
15 | send "1"
16 | expect {
17 | "Master password:" {
18 | send "1"
19 | expect {
20 | "4ui?YtkC[}e[XHCYs.r9Zsd{NC+aDl/US?h9A)58!"
21 | }}}}
22 |
23 | timeout {
24 | puts "genpass failed";
25 | exit 1
26 | }
27 | }'
28 |
29 | printf "%s\\n" "${expect_script}" > /tmp/genpass-site-and-mp-input.exp
30 | expect /tmp/genpass-site-and-mp-input.exp
31 |
--------------------------------------------------------------------------------
/test/genpass-static.db:
--------------------------------------------------------------------------------
1 | @begin{essential}
2 | test -f ../../genpass
3 | test -f ../../genpass-static
4 | @end
5 |
6 | @begin{return-codes}
7 | genpass-static -h; test X"${?}" = X"0"
8 | genpass-static -V; test X"${?}" = X"0"
9 | genpass-static -n; test X"${?}" = X"1"
10 | genpass-static -p; test X"${?}" = X"1"
11 | genpass-static -s; test X"${?}" = X"1"
12 | genpass-static -f; test X"${?}" = X"1"
13 | genpass-static -l; test X"${?}" = X"1"
14 | genpass-static -C; test X"${?}" = X"1"
15 | genpass-static -c; test X"${?}" = X"1"
16 | genpass-static --scrypt-r; test X"${?}" = X"1"
17 | genpass-static --scrypt-p; test X"${?}" = X"1"
18 | genpass-static --config; test X"${?}" = X"1"
19 | genpass-static --cui; test X"${?}" = X"1"
20 |
21 | printf "%s" '-h' | genpass-static -f ./key -C1 -c1 -n1 -p1 1; test X"${?}" = X"0"
22 | #test ! -f ./key #TODO 10-10-2016 03:17 >> fix bug
23 | @end
24 |
25 | @begin{error-messages}
26 | test X"$(genpass-static -h |head -1)" = X"Usage: genpass [option]... [site]"
27 | test X"$(genpass-static --help |head -1)" = X"Usage: genpass [option]... [site]"
28 | test X"$(genpass-static --cui 2>&1|head -1)" = X"genpass: unrecognized option '--cui'"
29 | test X"$(genpass-static --cui |head -1)" = X""
30 | test X"$(genpass-static -n 2>&1|head -1)" = X"genpass: option '-n' requires an argument"
31 | test X"$(genpass-static -n |head -1)" = X""
32 | test X"$(genpass-static -l a 2>&1|head -1)" = X"genpass: option '-l' requires a numerical argument, 'a'"
33 | test X"$(genpass-static -la 2>&1|head -1)" = X"genpass: option '-l' requires a numerical argument, 'a'"
34 | test X"$(genpass-static -la |head -1)" = X""
35 | test X"$(genpass-static -l1 2>&1|head -1)" = X"genpass: option '-l' numerical value must be between 8-1024, '1'"
36 | test X"$(genpass-static -C a 2>&1|head -1)" = X"genpass: option '-C' requires a numerical argument, 'a'"
37 | test X"$(genpass-static -C121 2>&1|head -1)" = X"genpass: option '-C' numerical value must be between 1-30, '121'"
38 | test X"$(genpass-static -c a 2>&1|head -1)" = X"genpass: option '-c' requires a numerical argument, 'a'"
39 | test X"$(genpass-static -c121 2>&1|head -1)" = X"genpass: option '-c' numerical value must be between 1-30, '121'"
40 | test X"$(genpass-static -e d 2>&1|head -1)" = X"genpass: invalid text encoding 'd'"
41 | test X"$(genpass-static --config 2>&1|head -1)" = X"genpass: option '--config' requires an argument"
42 | test X"$(genpass-static --config cui 2>&1|head -1)" = X"genpass: couldn't load config file 'cui'"
43 | test X"$(genpass-static --scrypt-r 2>&1|head -1)" = X"genpass: option '--scrypt-r' requires an argument"
44 | test X"$(genpass-static --scrypt-r a 2>&1|head -1)" = X"genpass: option '--scrypt-r' requires a numerical argument, 'a'"
45 | test X"$(genpass-static --scrypt-r 10291 2>&1|head -1)" = X"genpass: option '--scrypt-r' numerical value must be between 1-9999, '10291'"
46 | test X"$(genpass-static --scrypt-p 2>&1|head -1)" = X"genpass: option '--scrypt-p' requires an argument"
47 | test X"$(genpass-static --scrypt-p a 2>&1|head -1)" = X"genpass: option '--scrypt-p' requires a numerical argument, 'a'"
48 | test X"$(genpass-static --scrypt-r 102911 2>&1|head -1)" = X"genpass: option '--scrypt-r' numerical value must be between 1-9999, '102911'"
49 | @end
50 |
51 | @begin{password-generation}
52 | test X"$(genpass-static -f ./key -C1 -c1 -n1 -p1 1)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
53 | test X"$(genpass-static -f ./key -C1 -c1 -n1 -p1 1 -e z85)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
54 | test X"$(genpass-static -f ./key -C1 -c1 -l8 -e dec -n1 -p1 1)" = X"57175901779215943103"
55 | test X"$(genpass-static -f ./key -C1 -c1 -l8 -e hex -n1 -p1 1)" = X"39af5ab15c9f2b67"
56 | test X"$(genpass-static -f ./key -C1 -c1 -l8 -e base64 -n1 -p1 1)" = X"Oa9asVyfK2c"
57 | test X"$(genpass-static -f ./key -C1 -c1 -l8 -e skey -n1 -p1 1)" = X"RYE EGAN LEAR MEAL USES LUCK"
58 | test -f ./key && rm -rf key
59 |
60 | test X"$(genpass-static -f ./key -C1 -c1 -n2 -p1 1)" = X"4Topkr=o[&1 | grep "Generating new cache key" >/dev/null 2>&1
66 | genpass-static -f ./key -v -C1 -c1 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
67 | genpass-static -f ./key -v -C1 -c1 -l8 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1
68 | genpass-static -f ./key -v -C1 -c1 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
69 | genpass-static -f ./key -v -C1 -c2 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
70 | genpass-static -f ./key -v -C2 -c1 -l8 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1
71 | genpass-static -f ./key -v -C2 -c1 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
72 | genpass-static -f ./key -v -C2 -c1 -l8 --scrypt-r 1 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1
73 | genpass-static -f ./key -v -C2 -c1 -l8 --scrypt-r 1 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
74 | genpass-static -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1
75 | genpass-static -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 2 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1
76 | genpass-static -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 2 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
77 | test -f ./key && rm -rf key
78 |
79 | genpass-static -f ./key -1 -v -c1 -n1 -p1 1 2>&1 | grep "Generating single derived key" >/dev/null 2>&1
80 | test ! -f ./key
81 | genpass-static -f ./key -N -v -C1 -c1 -n1 -p1 1 2>&1 | grep "Generating new cache key" >/dev/null 2>&1
82 | test ! -f ./key
83 | @end
84 |
85 | @begin{config-file}
86 | #TODO 03-10-2016 12:39 >> BUG, remove ''/"" from name user
87 | #printf "%s\\n%s\\n" "[user]" "name='1'" > genpass.config
88 | printf "%s\\n%s\\n" "[user]" "name=1" > genpass.config
89 | test X"$(genpass-static -f ./key --config genpass.config -C1 -c1 -p1 1)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
90 | printf "%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" > genpass.config
91 | test X"$(genpass-static -f ./key --config genpass.config -C1 -c1 -p1)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
92 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" "[general]" "cache_cost=1" > genpass.config
93 | test X"$(genpass-static -f ./key --config genpass.config -c1 -p1)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
94 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" "[general]" "cache_cost=1" "cost=1" > genpass.config
95 | test X"$(genpass-static -f ./key --config genpass.config -p1)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
96 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "password=1" "site=1" "[general]" "cache_cost=1" "cost=1" > genpass.config
97 | test X"$(genpass-static -f ./key --config genpass.config)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
98 | test -f genpass.config && rm -rf genpass.config
99 | @end
100 |
101 | @begin{interactive}
102 | #expect tests
103 | for genpass_test_exp in ../genpass*exp.sh; do sh "${genpass_test_exp}" || exit 1; done
104 | @end
105 |
106 | # vim: set ts=8 sw=4 tw=0 ft=sh :
107 |
--------------------------------------------------------------------------------
/test/getpass.db:
--------------------------------------------------------------------------------
1 | @begin{initializate}
2 | #use genpass-static to avoid depending on the user
3 | #installing genpass and libraries on its system
4 | cp ../../genpass ../../genpass.orig
5 | cp ../../genpass-static ../../genpass
6 | @end
7 |
8 | @begin{return-codes}
9 | getpass -h; test X"${?}" = X"0"
10 | getpass -V; test X"${?}" = X"0"
11 | getpass -n; test X"${?}" = X"1"
12 | getpass -p; test X"${?}" = X"1"
13 | getpass -s; test X"${?}" = X"1"
14 | getpass -f; test X"${?}" = X"1"
15 | getpass -l; test X"${?}" = X"1"
16 | getpass -C; test X"${?}" = X"1"
17 | getpass -c; test X"${?}" = X"1"
18 | getpass --scrypt-r; test X"${?}" = X"1"
19 | getpass --scrypt-p; test X"${?}" = X"1"
20 | getpass --config; test X"${?}" = X"1"
21 | getpass --cui; test X"${?}" = X"1"
22 |
23 | printf "%s" '-h' | getpass -f ./key -C1 -c1 -n1 -p1 1; test X"${?}" = X"0"
24 | test ! -f ./key
25 | @end
26 |
27 | @begin{error-messages}
28 | test X"$(getpass -h |head -1)" = X"Usage: getpass [option]... site"
29 | test X"$(getpass --help |head -1)" = X"Usage: getpass [option]... site"
30 | test X"$(getpass --cui 2>&1|head -1)" = X"genpass: unrecognized option '--cui'"
31 | test X"$(getpass --cui |head -1)" = X""
32 | test X"$(getpass -n 2>&1|head -1)" = X"genpass: option '-n' requires an argument"
33 | test X"$(getpass -n |head -1)" = X""
34 | test X"$(getpass -l a 2>&1|head -1)" = X"genpass: option '-l' requires a numerical argument, 'a'"
35 | test X"$(getpass -la 2>&1|head -1)" = X"genpass: option '-l' requires a numerical argument, 'a'"
36 | test X"$(getpass -la |head -1)" = X""
37 | test X"$(getpass -l1 2>&1|head -1)" = X"genpass: option '-l' numerical value must be between 8-1024, '1'"
38 | test X"$(getpass -C a 2>&1|head -1)" = X"genpass: option '-C' requires a numerical argument, 'a'"
39 | test X"$(getpass -C121 2>&1|head -1)" = X"genpass: option '-C' numerical value must be between 1-30, '121'"
40 | test X"$(getpass -c a 2>&1|head -1)" = X"genpass: option '-c' requires a numerical argument, 'a'"
41 | test X"$(getpass -c121 2>&1|head -1)" = X"genpass: option '-c' numerical value must be between 1-30, '121'"
42 | test X"$(getpass -e d 2>&1|head -1)" = X"genpass: invalid text encoding 'd'"
43 | test X"$(getpass --scrypt-r 2>&1|head -1)" = X"genpass: option '--scrypt-r' requires an argument"
44 | test X"$(getpass --scrypt-r a 2>&1|head -1)" = X"genpass: option '--scrypt-r' requires a numerical argument, 'a'"
45 | test X"$(getpass --scrypt-r 10291 2>&1|head -1)" = X"genpass: option '--scrypt-r' numerical value must be between 1-9999, '10291'"
46 | test X"$(getpass --scrypt-p 2>&1|head -1)" = X"genpass: option '--scrypt-p' requires an argument"
47 | test X"$(getpass --scrypt-p a 2>&1|head -1)" = X"genpass: option '--scrypt-p' requires a numerical argument, 'a'"
48 | test X"$(getpass --scrypt-r 102911 2>&1|head -1)" = X"genpass: option '--scrypt-r' numerical value must be between 1-9999, '102911'"
49 | test X"$(getpass --config 2>&1|head -1)" = X"genpass: option '--config' requires an argument"
50 | test X"$(getpass --config cui 2>&1|head -1)" = X"genpass: couldn't load config file 'cui'"
51 | @end
52 |
53 | @begin{password-generation}
54 | getpass -f ./key -C1 -c1 -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
55 | getpass -f ./key -C1 -c1 -n1 -p1 1 -e z85 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
56 | getpass -f ./key -C1 -c1 -l8 -e dec -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"57175901779215943103"
57 | getpass -f ./key -C1 -c1 -l8 -e hex -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"39af5ab15c9f2b67"
58 | getpass -f ./key -C1 -c1 -l8 -e base64 -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"Oa9asVyfK2c"
59 | getpass -f ./key -C1 -c1 -l8 -e skey -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"RYE EGAN LEAR MEAL USES LUCK"
60 | test -f ./key && rm -rf key
61 |
62 | getpass -f ./key -C1 -c1 -n2 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"4Topkr=o[&1 | grep "Generating new cache key" >/dev/null 2>&1
68 | getpass -f ./key -v -C1 -c1 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
69 | getpass -f ./key -v -C1 -c1 -l8 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1
70 | getpass -f ./key -v -C1 -c1 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
71 | getpass -f ./key -v -C1 -c2 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
72 | getpass -f ./key -v -C2 -c1 -l8 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1
73 | getpass -f ./key -v -C2 -c1 -l8 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
74 | getpass -f ./key -v -C2 -c1 -l8 --scrypt-r 1 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1
75 | getpass -f ./key -v -C2 -c1 -l8 --scrypt-r 1 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
76 | getpass -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 1 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1
77 | getpass -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 2 -n1 -p1 1 2>&1 | grep "Invalid cache key value" >/dev/null 2>&1
78 | getpass -f ./key -v -C2 -c1 -l8 --scrypt-r 2 --scrypt-p 2 -n1 -p1 1 2>&1 | grep "Loaded valid cache key value" >/dev/null 2>&1
79 | test -f ./key && rm -rf key
80 | getpass -f ./key -1 -v -c1 -n1 -p1 1 2>&1 | grep "Generating single derived key" >/dev/null 2>&1
81 | test ! -f ./key
82 | getpass -f ./key -N -v -C1 -c1 -n1 -p1 1 2>&1 | grep "Generating new cache key" >/dev/null 2>&1
83 | test ! -f ./key
84 | getpass -k 1 -f ./key -C1 -c1 -n1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
85 | test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
86 | sleep 1.1 || sleep 2 && test X"$(xclip -o -selection clipboard)" = X""
87 | @end
88 |
89 | @begin{config-file}
90 | #TODO 03-10-2016 12:39 >> BUG, remove ''/"" from name user
91 | #printf "%s\\n%s\\n" "[user]" "name='1'" > genpass.config
92 | printf "%s\\n%s\\n" "[user]" "name=1" > genpass.config
93 | getpass -f ./key --config genpass.config -C1 -c1 -p1 1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
94 | printf "%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" > genpass.config
95 | getpass -f ./key --config genpass.config -C1 -c1 -p1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
96 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" "[general]" "cache_cost=1" > genpass.config
97 | getpass -f ./key --config genpass.config -c1 -p1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
98 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "site=1" "[general]" "cache_cost=1" "cost=1" > genpass.config
99 | getpass -f ./key --config genpass.config -p1 && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
100 | printf "%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n" "[user]" "name=1" "password=1" "site=1" "[general]" "cache_cost=1" "cost=1" > genpass.config
101 | getpass -f ./key --config genpass.config && test X"$(xclip -o -selection clipboard)" = X"4>KGf9&t4Xl?:6V+5jSV1ttxP56oiwW>/XmZ^dr{N"
102 | test -f genpass.config && rm -rf genpass.config
103 | @end
104 |
105 | @begin{cleanup}
106 | #revert tmp changes, see {initializate} test
107 | mv ../../genpass.orig ../../genpass
108 | @end
109 |
110 | # vim: set ts=8 sw=4 tw=0 ft=sh :
111 |
--------------------------------------------------------------------------------
/test/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #usage: ./test.sh [tool] [test]
3 | #based on the GNU shtool test suite
4 |
5 | _false() { return 1; }
6 |
7 | CURRENT_DIR="$(cd "$(dirname "${0}")" && pwd)"
8 | cd "${CURRENT_DIR}"
9 |
10 | #override temp debug string, avoid "Bad substitution" errors
11 | PS4=">>"
12 |
13 | TMPDIR="test.tmp"
14 | TMPSCRIPT="test.tmp.sh"
15 |
16 | #initial score values
17 | failed="0"; passed="0"; ran="0"
18 |
19 | #use default or user input ($1)
20 | [ -z "${1}" ] && db_tests="*.db" || db_tests="${1%.db}.db"
21 |
22 | for db_test in "${CURRENT_DIR}"/${db_tests}; do
23 | tool="$(basename "${db_test}")"; tool="${tool%.db}"
24 |
25 | #check tool existence
26 | if [ -f ../"${tool}" ]; then
27 | printf "%s\\n\\n" "Info - running '${tool}' tests:"
28 | else
29 | printf "%s\\n" "Warning - '${tool}' doesn't exists, skipping ..."
30 | _false
31 | continue
32 | fi
33 |
34 | #read all tests defined in *.db files or user input ($2)
35 | tests=""; if [ -z "${2}" ]; then
36 | tests="$(grep '^@begin' "${db_test}" 2>/dev/null | \
37 | sed -e 's/^@begin{//' -e 's/}.*$//')"
38 | else
39 | tests="${2}"
40 | fi
41 |
42 | #move to a tmp subdirectory
43 | rm -rf "${TMPDIR}" || (sleep 1; rm -rf "${TMPDIR}")
44 | mkdir "${TMPDIR}" || exit 1
45 | cd "${TMPDIR}" || exit 1
46 |
47 | OLDIFS="${IFS}"; IFS='
48 | ' #this a new line
49 | for test in ${tests}; do
50 | #check tests exists
51 | if ! grep "^@begin{$test}" "${db_test}" >/dev/null 2>&1; then
52 | printf "%s\\n" "Warning - '${tool}' doesn't exists, skipping ..."
53 | _false
54 | continue
55 | fi
56 |
57 | #clean tmp directory
58 | rm -rf ./* || (sleep 1; rm -rf ./*)
59 | #print test title
60 | printf "%s %s\\n" "${test}" "$(printf "%*s" "65" ""|tr ' ' '.')" | \
61 | awk '{printf("%s ", substr($0, 0, 65));}'
62 |
63 | #generate tmp test script
64 | printf "%s\\n" "PATH=../..:/bin:/usr/bin" > "${TMPSCRIPT}"
65 | sed -e "/^@begin{$test}/,/^@end/p" -e '1,$d' "${db_test}" | \
66 | sed -e '/^@begin/d' -e '/^@end/d' \
67 | -e 's/\([^\\]\)[ ]*$/\1 || exit 1/g' >> "${TMPSCRIPT}"
68 | printf "exit 0\\n" >> "${TMPSCRIPT}"
69 |
70 | #execute current test
71 | sh -x "${TMPSCRIPT}" > "${TMPSCRIPT%.sh}.log" 2>&1
72 |
73 | #validate test result
74 | if [ "${?}" -eq "0" ]; then
75 | passed="$((${passed} + 1))"
76 | printf "ok\\n"
77 | else
78 | #generate report
79 | printf "FAILED\\n"
80 | printf "+---Test------------------------------\\n"
81 | cat "${TMPSCRIPT}" | sed -e 's/^/| /g'
82 | printf "+---Trace-----------------------------\\n"
83 | cat "${TMPSCRIPT%.sh}.log" | sed -e 's/^/| /g'
84 | failed="$((${failed} + 1))"
85 | printf "+-------------------------------------\\n"
86 | fi
87 |
88 | ran="$((${ran} + 1))"
89 | done
90 |
91 | IFS="${OLDIFS}"
92 | cd .. && rm -rf "${TMPDIR}" >/dev/null 2>&1
93 | printf "\\n"
94 | done
95 |
96 | #result and cleanup
97 | if [ "${failed}" -gt "0" ]; then
98 | printf "FAILED: passed: ${passed}/${ran}, failed: ${failed}/${ran}\\n"
99 | exit 1
100 | else
101 | printf "OK: passed: ${passed}/${ran}\\n"
102 | fi
103 |
104 | # vim: set ts=8 sw=4 tw=0 ft=sh :
105 |
--------------------------------------------------------------------------------