Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Robert Dubner
OpenLDAP
Commits
a715ee23
Commit
a715ee23
authored
Oct 13, 2021
by
Robert Dubner
Browse files
Sanitized SHA-1
parent
1b77bac5
Changes
8
Hide whitespace changes
Inline
Side-by-side
contrib/slapd-modules/radiusov/demonstration/radiusclient/md4.c
View file @
a715ee23
/* md4.c */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2021 The OpenLDAP Foundation.
* Portions Copyright 2021 Robert Dubner, Symas Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
...
...
@@ -13,74 +11,14 @@
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*
*
The code in
this
m
od
ule is largely
derived from
a
public
domain source
.
*
As noted below, portions of
this
c
od
e were
derived from public
-
domain source
s
*
*/
#include
"md4.h"
#define HAVE_SYS_TYPES_H 1
#define HAVE_STDINT_H 1
/** Convert UTF8 string to UCS2 encoding
*
* @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
*
* @param[out] out Where to write the ucs2 string.
* @param[in] outlen Size of output buffer.
* @param[in] in UTF8 string to convert.
* @param[in] inlen length of UTF8 string.
* @return the size of the UCS2 string written to the output buffer (in bytes).
*/
ssize_t
utf8_to_ucs2
(
uint8_t
*
out
,
size_t
outlen
,
char
const
*
in
,
size_t
inlen
)
{
size_t
i
;
uint8_t
*
start
=
out
;
for
(
i
=
0
;
i
<
inlen
;
i
++
)
{
uint8_t
c
,
c2
,
c3
;
c
=
in
[
i
];
if
((
size_t
)(
out
-
start
)
>=
outlen
)
{
/* input too long */
return
-
1
;
}
/* One-byte encoding */
if
(
c
<=
0x7f
)
{
PUT_LE16
(
out
,
c
);
out
+=
2
;
continue
;
}
else
if
((
i
==
(
inlen
-
1
))
||
((
size_t
)(
out
-
start
)
>=
(
outlen
-
1
)))
{
/* Incomplete surrogate */
return
-
1
;
}
c2
=
in
[
++
i
];
/* Two-byte encoding */
if
((
c
&
0xe0
)
==
0xc0
)
{
PUT_LE16
(
out
,
((
c
&
0x1f
)
<<
6
)
|
(
c2
&
0x3f
));
out
+=
2
;
continue
;
}
if
((
i
==
inlen
)
||
((
size_t
)(
out
-
start
)
>=
(
outlen
-
1
)))
{
/* Incomplete surrogate */
return
-
1
;
}
/* Three-byte encoding */
c3
=
in
[
++
i
];
PUT_LE16
(
out
,
((
c
&
0xf
)
<<
12
)
|
((
c2
&
0x3f
)
<<
6
)
|
(
c3
&
0x3f
));
out
+=
2
;
}
return
out
-
start
;
}
#include
"md4.h"
/** Calculate the MD4 hash of the contents of a buffer
*
...
...
contrib/slapd-modules/radiusov/demonstration/radiusclient/md4.h
View file @
a715ee23
/* md4.h */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2021 The OpenLDAP Foundation.
* Portions Copyright 2021 Robert Dubner, Symas Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
...
...
@@ -13,15 +11,12 @@
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*
*
The code in
this
m
od
ule is largely
derived from
a
public
domain source
.
*
As noted below, portions of
this
c
od
e were
derived from public
-
domain source
s
*
*/
#include
"stdint.h"
#include
"sys/types.h"
#ifndef _MD4_H
#define _MD4_H
#ifndef _h_MD4_H
#define _h_MD4_H
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
...
...
@@ -37,10 +32,6 @@
#include
<string.h>
#ifdef HAVE_OPENSSL_MD4_H
# include <openssl/md4.h>
#endif
#ifdef __cplusplus
extern
"C"
{
#endif
...
...
@@ -67,8 +58,6 @@ extern "C" {
# define MD4_BLOCK_LENGTH 64
# define MD4_DIGEST_STRING_LENGTH (MD4_DIGEST_LENGTH * 2 + 1)
ssize_t
utf8_to_ucs2
(
uint8_t
*
out
,
size_t
outlen
,
char
const
*
in
,
size_t
inlen
);
typedef
struct
MD4Context
{
uint32_t
state
[
4
];
//!< State.
...
...
@@ -83,12 +72,6 @@ void md4_transform(uint32_t buf[4], uint8_t const inc[MD4_BLOCK_LENGTH]);
void
md4_calc
(
uint8_t
out
[
MD4_DIGEST_LENGTH
],
uint8_t
const
*
in
,
size_t
inlen
);
#define PUT_LE16(a, val)\
do {\
a[1] = ((uint16_t) (val)) >> 8;\
a[0] = ((uint16_t) (val)) & 0xff;\
} while (0)
#ifdef __cplusplus
}
#endif
...
...
contrib/slapd-modules/radiusov/demonstration/radiusclient/mschap.c
View file @
a715ee23
...
...
@@ -19,6 +19,9 @@
* http://www.freeradius.org/rfc/rfc2548.txt
*
*/
#define HAVE_SYS_TYPES_H 1
#define HAVE_STDINT_H 1
#include
"md4.h"
#include
"mschap.h"
...
...
@@ -74,15 +77,15 @@ mschap_challenge_hash(const uint8_t *peer_challenge,
const
char
*
user_name
,
uint8_t
*
challenge
)
{
sha1_ctx
Context
;
SHA1_CTX
Context
;
uint8_t
hash
[
20
];
sha1_i
nit
(
&
Context
);
sha1_u
pdate
(
&
Context
,
peer_challenge
,
16
);
sha1_u
pdate
(
&
Context
,
auth_challenge
,
16
);
sha1_u
pdate
(
&
Context
,
(
uint8_t
const
*
)
user_name
,
SHA1I
nit
(
&
Context
);
SHA1U
pdate
(
&
Context
,
peer_challenge
,
16
);
SHA1U
pdate
(
&
Context
,
auth_challenge
,
16
);
SHA1U
pdate
(
&
Context
,
(
uint8_t
const
*
)
user_name
,
strlen
(
user_name
));
sha1_f
inal
(
hash
,
&
Context
);
SHA1F
inal
(
hash
,
&
Context
);
memcpy
(
challenge
,
hash
,
8
);
}
...
...
@@ -102,7 +105,7 @@ GenerateAuthenticatorResponse( uint8_t const *unicode_password,
{
// See RFC2759 Section 8.7
sha1_ctx
Context
;
SHA1_CTX
Context
;
static
const
uint8_t
magic1
[
39
]
=
{
0x4D
,
0x61
,
0x67
,
0x69
,
0x63
,
0x20
,
0x73
,
0x65
,
0x72
,
0x76
,
...
...
@@ -133,17 +136,17 @@ GenerateAuthenticatorResponse( uint8_t const *unicode_password,
// Hash the hash
NTPasswordHash
(
nt_hash
,
MD4_DIGEST_LENGTH
,
nt_hash_hash
);
sha1_i
nit
(
&
Context
);
sha1_u
pdate
(
&
Context
,
nt_hash_hash
,
16
);
sha1_u
pdate
(
&
Context
,
ntresponse
,
24
);
sha1_u
pdate
(
&
Context
,
magic1
,
39
);
sha1_f
inal
(
digest
,
&
Context
);
SHA1I
nit
(
&
Context
);
SHA1U
pdate
(
&
Context
,
nt_hash_hash
,
16
);
SHA1U
pdate
(
&
Context
,
ntresponse
,
24
);
SHA1U
pdate
(
&
Context
,
magic1
,
39
);
SHA1F
inal
(
digest
,
&
Context
);
mschap_challenge_hash
(
peer_challenge
,
auth_challenge
,
username
,
challenge
);
sha1_i
nit
(
&
Context
);
sha1_u
pdate
(
&
Context
,
digest
,
20
);
sha1_u
pdate
(
&
Context
,
challenge
,
8
);
sha1_u
pdate
(
&
Context
,
magic2
,
41
);
sha1_f
inal
(
digest
,
&
Context
);
SHA1I
nit
(
&
Context
);
SHA1U
pdate
(
&
Context
,
digest
,
20
);
SHA1U
pdate
(
&
Context
,
challenge
,
8
);
SHA1U
pdate
(
&
Context
,
magic2
,
41
);
SHA1F
inal
(
digest
,
&
Context
);
/*
* Encode the value of 'Digest' as "S=" followed by
...
...
@@ -172,16 +175,16 @@ ChallengeHash( const uint8_t *peer_challenge,
uint8_t
*
Challenge
)
{
// RFC2759 Section 8.2
sha1_ctx
Context
;
sha1_ctx
*
context
=
&
Context
;
SHA1_CTX
Context
;
SHA1_CTX
*
context
=
&
Context
;
sha1_i
nit
(
context
);
sha1_u
pdate
(
context
,
peer_challenge
,
16
);
sha1_u
pdate
(
context
,
authenticator_challenge
,
16
);
sha1_u
pdate
(
context
,
(
uint8_t
*
)
username
,
strlen
(
username
));
SHA1I
nit
(
context
);
SHA1U
pdate
(
context
,
peer_challenge
,
16
);
SHA1U
pdate
(
context
,
authenticator_challenge
,
16
);
SHA1U
pdate
(
context
,
(
uint8_t
*
)
username
,
strlen
(
username
));
uint8_t
Digest
[
20
];
sha1_f
inal
(
Digest
,
context
);
SHA1F
inal
(
Digest
,
context
);
memcpy
(
Challenge
,
Digest
,
8
);
}
...
...
contrib/slapd-modules/radiusov/demonstration/radiusclient/mschap.h
View file @
a715ee23
...
...
@@ -17,8 +17,14 @@
*
*/
#ifndef _MSCHAP_H
#define _MSCHAP_H
#ifndef _h_MSCHAP_H
#define _h_MSCHAP_H
#include
<sys/types.h>
#include
<stdint.h>
#define HAVE_SYS_TYPES_H 1
#define HAVE_STDINT_H 1
#define NT_DIGEST_LENGTH 16
...
...
contrib/slapd-modules/radiusov/demonstration/radiusclient/radiusclient.c
View file @
a715ee23
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2021 The OpenLDAP Foundation.
* Portions Copyright 2021 Robert Dubner, Symas Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#define HAVE_SYS_TYPES_H 1
#define HAVE_STDINT_H 1
#include
<poll.h>
#include
<unistd.h>
...
...
@@ -931,6 +948,76 @@ process_the_received_packet(CLIENT_STATE *state)
return
RCV_START
;
}
#define PUT_LE16(a, val)\
do {\
a[1] = ((uint16_t) (val)) >> 8;\
a[0] = ((uint16_t) (val)) & 0xff;\
} while (0)
static
ssize_t
utf8_to_ucs2
(
uint8_t
*
out
,
size_t
outlen
,
char
const
*
in
,
size_t
inlen
)
{
// We always output UCS2 characters two bytes at a time, so make sure
// our caller called us with an even number as the outlen
outlen
&=
~
1
;
// Converts a UTF8 string into a UCS2 string
size_t
i
=
0
;
uint8_t
*
start
=
out
;
while
(
i
<
inlen
)
{
uint8_t
c
;
uint8_t
c2
;
uint8_t
c3
;
if
((
size_t
)(
out
-
start
)
>=
outlen
)
{
// We ran out of room in the destination
return
-
1
;
}
c
=
in
[
i
++
];
if
(
c
<=
0x7f
)
{
// This is a single-byte character, just output it as a
// 16-bit little-endian character
PUT_LE16
(
out
,
c
);
out
+=
2
;
continue
;
}
if
(
i
>=
inlen
)
{
// Odd. We need at least one more character, but the input
// buffer ran out
return
-
1
;
}
c2
=
in
[
i
++
];
if
((
c
&
0xe0
)
==
0xc0
)
{
// This is a two-byte character.
PUT_LE16
(
out
,
((
c
&
0x1f
)
<<
6
)
|
(
c2
&
0x3f
));
out
+=
2
;
continue
;
}
if
(
i
>=
inlen
)
{
// We need a third character, but we fell off the edge of the input
return
-
1
;
}
/* Three-byte encoding */
c3
=
in
[
i
++
];
PUT_LE16
(
out
,
((
c
&
0xf
)
<<
12
)
|
((
c2
&
0x3f
)
<<
6
)
|
(
c3
&
0x3f
));
out
+=
2
;
}
// Return the length, in bytes, of the UCS2-encoded string
return
out
-
start
;
}
static
int
BuildMschapResponseFromChallenge
(
CLIENT_STATE
*
state
,
MSCHAP_RESPONSE
*
response
,
...
...
contrib/slapd-modules/radiusov/demonstration/radiusclient/sha1.c
View file @
a715ee23
...
...
@@ -16,151 +16,191 @@
*
*/
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
100% Public Domain
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#define SHA1HANDSOFF
#include
<stdio.h>
#include
<string.h>
#include
<arpa/inet.h>
/* for uint32_t */
#include
<stdint.h>
#include
"sha1.h"
# define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
# define blk0(i) (block->l[i] = htonl(block->l[i]))
# define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
#if BYTE_ORDER == LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#elif BYTE_ORDER == BIG_ENDIAN
#define blk0(i) block->l[i]
#else
#error "Endianness not defined!"
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
# define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
# define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
# define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
# define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
# define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */
void
sha1_transform
(
uint32_t
state
[
5
],
uint8_t
const
buffer
[
64
])
{
void
SHA1Transform
(
uint32_t
state
[
5
],
const
unsigned
char
buffer
[
64
]
)
{
uint32_t
a
,
b
,
c
,
d
,
e
;
typedef
union
{
u
int8_t
c
[
64
];
{
u
nsigned
char
c
[
64
];
uint32_t
l
[
16
];
}
CHAR64LONG16
;
CHAR64LONG16
*
block
;
uint8_t
workspace
[
64
];
}
CHAR64LONG16
;
block
=
(
CHAR64LONG16
*
)
workspace
;
memcpy
(
block
,
buffer
,
64
);
#ifdef SHA1HANDSOFF
CHAR64LONG16
block
[
1
];
/* use array to appear as a pointer */
memcpy
(
block
,
buffer
,
64
);
#else
/* The following had better never be used because it causes the
* pointer-to-const buffer to be cast into a pointer to non-const.
* And the result is written through. I threw a "const" in, hoping
* this will cause a diagnostic.
*/
CHAR64LONG16
*
block
=
(
const
CHAR64LONG16
*
)
buffer
;
#endif
/* Copy context->state[] to working vars */
a
=
state
[
0
];
b
=
state
[
1
];
c
=
state
[
2
];
d
=
state
[
3
];
e
=
state
[
4
];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0
(
a
,
b
,
c
,
d
,
e
,
0
);
R0
(
e
,
a
,
b
,
c
,
d
,
1
);
R0
(
d
,
e
,
a
,
b
,
c
,
2
);
R0
(
c
,
d
,
e
,
a
,
b
,
3
);
R0
(
b
,
c
,
d
,
e
,
a
,
4
);
R0
(
a
,
b
,
c
,
d
,
e
,
5
);
R0
(
e
,
a
,
b
,
c
,
d
,
6
);
R0
(
d
,
e
,
a
,
b
,
c
,
7
);
R0
(
c
,
d
,
e
,
a
,
b
,
8
);
R0
(
b
,
c
,
d
,
e
,
a
,
9
);
R0
(
a
,
b
,
c
,
d
,
e
,
10
);
R0
(
e
,
a
,
b
,
c
,
d
,
11
);
R0
(
d
,
e
,
a
,
b
,
c
,
12
);
R0
(
c
,
d
,
e
,
a
,
b
,
13
);
R0
(
b
,
c
,
d
,
e
,
a
,
14
);
R0
(
a
,
b
,
c
,
d
,
e
,
15
);
R1
(
e
,
a
,
b
,
c
,
d
,
16
);
R1
(
d
,
e
,
a
,
b
,
c
,
17
);
R1
(
c
,
d
,
e
,
a
,
b
,
18
);
R1
(
b
,
c
,
d
,
e
,
a
,
19
);
R2
(
a
,
b
,
c
,
d
,
e
,
20
);
R2
(
e
,
a
,
b
,
c
,
d
,
21
);
R2
(
d
,
e
,
a
,
b
,
c
,
22
);
R2
(
c
,
d
,
e
,
a
,
b
,
23
);
R2
(
b
,
c
,
d
,
e
,
a
,
24
);
R2
(
a
,
b
,
c
,
d
,
e
,
25
);
R2
(
e
,
a
,
b
,
c
,
d
,
26
);
R2
(
d
,
e
,
a
,
b
,
c
,
27
);
R2
(
c
,
d
,
e
,
a
,
b
,
28
);
R2
(
b
,
c
,
d
,
e
,
a
,
29
);
R2
(
a
,
b
,
c
,
d
,
e
,
30
);
R2
(
e
,
a
,
b
,
c
,
d
,
31
);
R2
(
d
,
e
,
a
,
b
,
c
,
32
);
R2
(
c
,
d
,
e
,
a
,
b
,
33
);
R2
(
b
,
c
,
d
,
e
,
a
,
34
);
R2
(
a
,
b
,
c
,
d
,
e
,
35
);
R2
(
e
,
a
,
b
,
c
,
d
,
36
);
R2
(
d
,
e
,
a
,
b
,
c
,
37
);
R2
(
c
,
d
,
e
,
a
,
b
,
38
);
R2
(
b
,
c
,
d
,
e
,
a
,
39
);
R3
(
a
,
b
,
c
,
d
,
e
,
40
);
R3
(
e
,
a
,
b
,
c
,
d
,
41
);
R3
(
d
,
e
,
a
,
b
,
c
,
42
);
R3
(
c
,
d
,
e
,
a
,
b
,
43
);
R3
(
b
,
c
,
d
,
e
,
a
,
44
);
R3
(
a
,
b
,
c
,
d
,
e
,
45
);
R3
(
e
,
a
,
b
,
c
,
d
,
46
);
R3
(
d
,
e
,
a
,
b
,
c
,
47
);
R3
(
c
,
d
,
e
,
a
,
b
,
48
);
R3
(
b
,
c
,
d
,
e
,
a
,
49
);
R3
(
a
,
b
,
c
,
d
,
e
,
50
);
R3
(
e
,
a
,
b
,
c
,
d
,
51
);
R3
(
d
,
e
,
a
,
b
,
c
,
52
);
R3
(
c
,
d
,
e
,
a
,
b
,
53
);
R3
(
b
,
c
,
d
,
e
,
a
,
54
);
R3
(
a
,
b
,
c
,
d
,
e
,
55
);
R3
(
e
,
a
,
b
,
c
,
d
,
56
);
R3
(
d
,
e
,
a
,
b
,
c
,
57
);
R3
(
c
,
d
,
e
,
a
,
b
,
58
);
R3
(
b
,
c
,
d
,
e
,
a
,
59
);
R4
(
a
,
b
,
c
,
d
,
e
,
60
);
R4
(
e
,
a
,
b
,
c
,
d
,
61
);
R4
(
d
,
e
,
a
,
b
,
c
,
62
);
R4
(
c
,
d
,
e
,
a
,
b
,
63
);
R4
(
b
,
c
,
d
,
e
,
a
,
64
);
R4
(
a
,
b
,
c
,
d
,
e
,
65
);
R4
(
e
,
a
,
b
,
c
,
d
,
66
);
R4
(
d
,
e
,
a
,
b
,
c
,
67
);
R4
(
c
,
d
,
e
,
a
,
b
,
68
);
R4
(
b
,
c
,
d
,
e
,
a
,
69
);
R4
(
a
,
b
,
c
,
d
,
e
,
70
);
R4
(
e
,
a
,
b
,
c
,
d
,
71
);
R4
(
d
,
e
,
a
,
b
,
c
,
72
);
R4
(
c
,
d
,
e
,
a
,
b
,
73
);
R4
(
b
,
c
,
d
,
e
,
a
,
74
);
R4
(
a
,
b
,
c
,
d
,
e
,
75
);
R4
(
e
,
a
,
b
,
c
,
d
,
76
);
R4
(
d
,
e
,
a
,
b
,
c
,
77
);
R4
(
c
,
d
,
e
,
a
,
b
,
78
);
R4
(
b
,
c
,
d
,
e
,
a
,
79
);
R0
(
a
,
b
,
c
,
d
,
e
,
0
);
R0
(
e
,
a
,
b
,
c
,
d
,
1
);
R0
(
d
,
e
,
a
,
b
,
c
,
2
);
R0
(
c
,
d
,
e
,
a
,
b
,
3
);
R0
(
b
,
c
,
d
,
e
,
a
,
4
);
R0
(
a
,
b
,
c
,
d
,
e
,
5
);
R0
(
e
,
a
,
b
,
c
,
d
,
6
);
R0
(
d
,
e
,
a
,
b
,
c
,
7
);
R0
(
c
,
d
,
e
,
a
,
b
,
8
);
R0
(
b
,
c
,
d
,
e
,
a
,
9
);
R0
(
a
,
b
,
c
,
d
,
e
,
10
);
R0
(
e
,
a
,
b
,
c
,
d
,
11
);
R0
(
d
,
e
,
a
,
b
,
c
,
12
);
R0
(
c
,
d
,
e
,
a
,
b
,
13
);
R0
(
b
,
c
,
d
,
e
,
a
,
14
);
R0
(
a
,
b
,
c
,
d
,
e
,
15
);
R1
(
e
,
a
,
b
,
c
,
d
,
16
);
R1
(
d
,
e
,
a
,
b
,
c
,
17
);
R1
(
c
,
d
,
e
,
a
,
b
,
18
);
R1
(
b
,
c
,
d
,
e
,
a
,
19
);
R2
(
a
,
b
,
c
,
d
,
e
,
20
);
R2
(
e
,
a
,
b
,
c
,
d
,
21
);
R2
(
d
,
e
,
a
,
b
,
c
,
22
);
R2
(
c
,
d
,
e
,
a
,
b
,
23
);
R2
(
b
,
c
,
d
,
e
,
a
,
24
);
R2
(
a
,
b
,
c
,
d
,
e
,
25
);
R2
(
e
,
a
,
b
,
c
,
d
,
26
);
R2
(
d
,
e
,
a
,
b
,
c
,
27
);
R2
(
c
,
d
,
e
,
a
,
b
,
28
);
R2
(
b
,
c
,
d
,
e
,
a
,
29
);
R2
(
a
,
b
,
c
,
d
,
e
,
30
);
R2
(
e
,
a
,
b
,
c
,
d
,
31
);
R2
(
d
,
e
,
a
,
b
,
c
,
32
);