aboutsummaryrefslogtreecommitdiff
path: root/games/minimal/mods/legacy/textures/dungeon_master.png
blob: d52d8ccd7d4c3fdd7288aca92f6294b5901f4a1a (plain)
ofshex dumpascii
0000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 c0 00 00 00 f0 08 03 00 00 00 61 78 9b .PNG........IHDR.............ax.
0020 98 00 00 00 24 50 4c 54 45 00 00 00 2c 16 00 49 24 00 6d 49 24 78 ff 00 80 00 00 80 80 00 c0 ff ....$PLTE...,..I$.mI$x..........
0040 00 ff 9c 00 ff e4 00 ff f3 89 ff ff ff 1d dc fb bc 00 00 0b 56 49 44 41 54 78 da ed dc 81 96 a3 ....................VIDATx......
0060 36 0c 40 d1 67 79 c9 64 f8 ff 0f 6e 62 33 08 23 09 08 c9 a6 99 d6 ea 39 dd ce 12 6c dd 31 86 00 6.@.gy.d...nb3.#.......9...l.1..
0080 ae 18 76 e2 b2 13 ff f6 fe 1d d0 01 1d d0 01 ff 39 00 25 de 0e a0 c4 53 00 a6 c8 b7 00 78 23 40 ..v.............9.%....S.....x#@
00a0 bb ad e1 36 40 89 30 01 20 37 01 5e 02 94 78 31 c0 76 8d 6d 60 16 5a c0 ba 0d a9 01 26 01 0a 53 ...6@.0..7.^..x1.v.m`.Z.....&..S
00c0 84 b3 00 00 d6 00 28 9d 6a e4 6c 8f 61 a6 8f 00 06 a0 4d cc f9 97 30 00 98 9b 31 80 e0 38 b6 e9 ......(.j.l.a.....M...0...1..8..
00e0 8b 05 d4 46 01 ea 1f d3 af af 44 b3 eb 44 30 80 92 97 0d 68 13 00 ed 09 07 c0 b4 35 02 80 4d 80 ...F......D..D0....h.......5..M.
0100 d2 fb f4 f7 32 a5 3e f7 de 00 34 2f 1a 80 b6 60 a2 05 a0 1f 73 01 64 75 fb 00 49 f7 90 35 40 3b ....2.>...4/...`....s.du..I..5@;
0120 44 8a 61 d9 8e da 35 5a 40 9c bf 40 03 c8 cd a6 10 20 21 20 4d c1 12 40 03 68 7e e2 10 00 24 8c D.a...5Z@..@......!.M..@.h~...$.
0140 16 20 9b 00 f2 ce 08 90 7c 40 d3 ea aa 93 00 40 03 90 63 00 b6 01 4c 80 94 24 04 50 22 06 c4 c7 ........|@.....@..c...L..$.P"...
0160 f0 4a b6 0f c0 01 88 64 3b 09 cc 00 24 88 00 d4 31 00 c0 00 d8 99 84 f0 18 00 0b c8 39 db 31 74 .J.....d;...$...1...........9.1t
0180 67 40 04 48 53 38 00 76 01 b2 03 20 1b 41 0c 90 53 00 15 18 00 a4 b6 7b 17 40 8e e7 80 39 15 11 g@.HS8.v.....A..S......{.@...9..
01a0 ce 01 3c 00 cc 3c 08 00 02 21 20 ad 00 6c 00 10 0f 90 77 01 c2 06 60 39 3e 21 20 25 6a ac 01 90 ..<..<...!...l....w...`9>!.%j...
01c0 a4 0d 0f c0 ab 00 6c 03 12 84 80 29 58 9f 85 76 01 82 08 d9 07 20 8a db 03 e8 f5 f2 6f 03 68 bf ......l....)X..v............o.h.
01e0 cb 50 00 e2 01 86 53 00 ce 00 84 1a 72 14 30 1c 01 94 4d 03 f2 34 40 76 01 cc d1 02 6c fe 35 23 .P....S.....r.0...M..4@v....l.5#
0200 d0 06 d0 23 28 ad 00 72 14 b0 10 70 d9 02 0c 11 c0 bd 0e c4 00 79 27 40 66 00 7f 0d 30 e5 7f 1e ...#(..r...p.........y'@f...0...
0220 90 d8 00 e8 8e 31 00 02 80 1c 04 54 ab 0b c0 01 d0 02 8a 20 06 68 df 01 c0 9b 04 b5 67 db bb 05 .....1.....T.........h......g...
0240 80 6c 01 06 bc 2f 43 11 80 33 80 4b 00 10 b1 02 e6 bc 16 fe 39 7f e7 2c 84 01 88 05 cc 02 9c 9b .l.../C..3.K........9..,........
0260 7a 4c fe 47 6f 68 c4 11 50 d3 6a 00 3a 00 2c 01 13 0c 07 40 0b 40 87 20 06 24 03 b0 57 32 59 01 zL.Goh..P.j.:.,....@.@...$..W2Y.
0280 b0 5f a7 f5 ce 3e 1a 00 05 08 42 11 37 63 89 a0 80 78 08 2c 20 6d 01 24 00 20 2c 07 02 18 d6 09 ._...>....B.7c...x.,.m.$..,.....
02a0 54 27 02 01 60 18 5a 00 08 ac 01 50 00 48 04 28 e9 85 00 44 7f 81 0a c0 02 86 c1 02 8a 00 11 03 T'..`.Z....P.H.(...D............
02c0 28 61 01 65 43 93 80 ee ef 8d c0 40 34 89 35 a2 c7 2a 00 b2 06 d4 d0 06 0a d4 01 68 a0 b3 5f b3 (a.eC......@4.5..*.........h.._.
02e0 b0 00 04 70 f6 87 7d 00 f6 c9 9c 76 ae dd 87 cf 46 5f 02 88 9f 8d 52 0c 04 00 8d 13 00 1d c1 18 ...p..}....v....F_....R.........
0300 50 74 cc bf c9 08 a0 bb 1b 40 21 f0 f8 c3 5d cd 1f 4d 23 7e b4 17 00 94 1e 01 82 47 93 36 ce 03 Pt.......@!...]..M#~.......G.6..
0320 34 0f bf 81 2d 00 87 01 97 37 00 08 47 00 f3 6c d4 b6 80 01 78 bb bf 1e 00 9a 09 a6 01 00 09 01 4...-....7..G..l....x...........
0340 e8 e5 60 f8 f9 58 00 10 80 17 03 10 41 47 00 41 c7 c0 1c ff 2e a0 e8 98 76 83 ca 21 00 14 c3 4b ..`..X......AG.A........v..!...K
0360 01 53 7f 30 fd 37 02 b0 1e 81 da 71 38 02 35 94 83 b8 00 f4 44 f4 3a 80 e6 df a4 52 c2 b9 a7 0e .S.0.7.....q8.5.....D.:....R....
0380 01 ab 37 2d 16 50 43 f3 7f 19 00 a7 7f db 00 9a fb f9 04 00 e8 2f ba 35 d8 ed e0 c3 81 1d d0 01 ..7-.PC............../.5........
03a0 1d d0 01 ff 39 00 25 de 0e a0 c4 53 80 f5 7a a1 37 02 d0 6e e3 4b 3d 25 c2 04 9c f5 42 5e 02 94 ....9.%....S..z.7..n.K=%....B^..
03c0 78 31 c0 76 8d 6d 60 16 fa 00 77 bd 90 49 80 ca 14 5e 0a f0 d6 0b 85 6f 50 00 07 e0 af 17 32 00 x1.v.m`...w..I...^.....oP.....2.
03e0 98 9b 09 01 6c 02 00 30 80 2c 76 bd 90 d0 34 d0 3c 3b 32 80 70 bd 50 9b 40 b3 5e c8 07 90 a3 c7 ....l..0.,v...4.<;2.p.P.@.^.....
0400 2e 9a c5 1a 00 e2 af 17 5a 01 24 7c 83 12 ae b7 69 01 e8 c7 02 80 fe 2e 5d c0 9c 59 0b 88 d6 0b ........Z.$|....i.......]..Y....
0420 2d 01 20 8b 68 01 71 fe 02 0d 20 37 9b 22 40 7c cb 39 2f 78 6a 00 1b eb 85 8e 01 40 c2 68 01 b2 -...h.q....7."@|.9/xj......@.h..
0440 07 d0 23 d1 07 a4 29 68 00 e1 7a a1 18 40 03 90 63 00 76 01 90 b7 46 80 14 03 34 02 40 db fb 3e ..#...)h..z..@..c.v...F...4.@..>
0460 00 0b 68 26 3a 0a b0 03 90 92 b8 80 29 7c 00 a2 e1 9d c7 27 41 ce 07 01 38 00 6f 0c bd 19 90 d8 ..h&:.......)|.....'A...8.o.....
0480 18 81 42 c0 00 40 6c 34 00 a9 00 89 00 48 13 16 e0 8f a1 c9 3f 7e f6 9a a6 68 01 88 38 6b 0d f0 ..B..@l4.....H......?~...h..8k..
04a0 00 9a 25 18 00 88 23 e0 62 7b 8a 00 90 b3 0f b0 02 03 b0 eb 85 02 00 21 20 1d 03 10 03 f4 22 0e ..%...#.b{.............!......".
04c0 2e 80 18 60 bb 4f 0e 40 87 a0 01 b0 d5 c2 10 37 10 03 c4 07 48 02 c0 39 84 40 76 00 b2 05 e0 04 ...`.O.@.......7....H..9.@v.....
04e0 40 b6 00 09 7c c0 14 16 90 f6 00 f0 d3 f4 1a 70 8b c3 00 fd 18 bc 12 c0 23 00 9e 01 60 01 76 0e @...|..........p........#...`.v.
0500 c7 00 11 4a 88 01 88 07 e0 d2 00 54 70 1a 00 49 22 40 93 7f 04 60 8a 8f 04 88 02 88 de 82 9a f3 ...J.......Tp..I"@...`..........
0520 d0 51 00 fa 91 e7 0e a1 f8 ab 04 ba 2b 8f 03 d2 1e 40 68 57 03 5a 00 5e 0b 5c 82 b1 46 62 00 12 .Q..........+....@hW.Z.^.\..Fb..
0540 03 c0 00 10 c1 f6 6e 01 2c 01 ed fd 40 04 b0 5f 25 b4 95 18 10 5f 89 75 12 34 23 e0 f7 be 02 20 ......n.,...@.._%...._.u.4#.....
0560 fa 49 03 28 bb 1c 02 68 2b 28 c0 08 02 c0 80 cd 5f 2f f0 b6 f7 16 d0 e4 6f 01 ac 01 20 42 03 68 .I.(...h+(......_/......o....B.h
0580 5b f0 01 9a ff e1 1b 1a 84 7d 80 0e a0 7b 4b 29 e5 9f 76 30 49 54 80 06 2a d3 16 d6 f9 27 cd 3f [........}...{K)..v0IT..*....'.?
05a0 ba a5 4c d2 02 6c ef c0 bc 24 c6 fb a8 0f b8 38 eb 85 5a 00 73 13 43 04 48 29 6d 01 c4 01 50 7b ..L..l...$.....8..Z.s.C.H)m...P{
05c0 77 00 66 12 95 ed 24 03 28 b1 06 5c 00 da fd 49 88 40 3b 82 46 20 84 00 24 ad 8f 00 6a ff 06 00 w.f...$.(..\...I.@;.F...$...j...
05e0 e0 34 50 bc 36 01 cd 80 79 4e 6f 5c 49 07 1f 40 30 07 34 fc c7 2a b6 77 fc 06 78 15 80 70 49 19 .4P.6...yNo\I..@0.4..*.w..x..pI.
0600 db 00 dd dd 00 88 01 76 1a 13 fe 06 d1 07 65 1e a0 ee 6f 00 1a 3c bc 18 04 af 77 38 05 f8 a1 9f .......v......e...o..<....w8....
0620 02 28 e1 c4 d3 69 d3 7b 00 90 2d 00 06 70 74 7f 1b cf 03 78 14 00 32 cb e1 fd 00 14 10 3e da 43 .(...i.{..-..pt....x..2......>.C
0640 13 c0 03 20 68 13 88 b0 b1 ff 8b 01 00 28 00 41 c7 60 dd bd 9f 80 ae 17 9a 7f 10 f0 00 4a 78 31 ....h........(.A.`...........Jx1
0660 40 80 69 28 9a 89 6c be 09 fa 93 50 5f 4e a9 40 01 5e 1b af 06 00 9a 8a e6 af 00 90 70 5d a7 1a @.i(..l....P_N.@.^..........p]..
0680 1a 8e fb 7c 1f 10 78 25 c0 06 00 f1 c3 d5 f3 6f 19 99 a2 bf e8 d6 e8 95 3d 3a a0 03 3a a0 03 7a ...|..x%.......o........=:..:..z
06a0 7d a1 5e 5f e8 ff 56 5f e8 e9 d5 eb 9f 5b 5f 68 80 1d 00 c0 a7 d6 17 02 10 23 70 0b 24 7d 64 7d }.^_..V_.....[_h.........#p.$}d}
06c0 a1 39 8b 18 30 67 f6 91 f5 85 c8 aa de 2d 90 f4 79 f5 85 14 c0 06 e0 93 eb 0b d9 ea 42 fb 05 92 .9..0g.......-..y...........B...
06e0 de 5f 5f 48 83 08 00 06 10 14 48 7a 7f 7d 21 09 ea 0b 69 fe b5 cb 10 40 5a 57 48 52 00 e4 bf 5e .__H......Hz.}!...i....@ZWHR...^
0700 5f 48 16 9f b0 00 39 00 80 54 c3 00 20 3f 54 5f 88 c7 eb 0b b1 59 5f 88 e5 e8 ec 03 92 01 e4 fc _H....9..T...?T_.....Y_.........
0720 48 7d 21 0f 90 77 01 82 07 b0 82 10 20 40 08 38 5e 5f e8 79 00 16 80 ee 9f 38 52 20 a9 05 70 0c H}!..w.......@.8^_.y.....8R...p.
0740 90 7d 80 df 42 0c 10 0f 90 0d e0 91 fa 42 f8 67 11 d6 00 f1 00 c3 07 03 86 18 60 eb 0b bd 01 40 .}..B........B.g..........`....@
0760 89 84 34 00 0e 8e 80 1e 41 2b 80 1c 05 a8 60 0b 20 69 07 00 1c 04 48 0b d0 2d a7 01 1c 29 90 b4 ..4.....A+....`..i....H..-...)..
0780 7b 08 b5 80 ba 0c 67 1f 80 26 76 1a a0 43 b0 51 20 09 39 01 10 db bd 0b 78 be be 50 0c 90 23 d7 {.....g..&v..C.Q..9.....x..P..#.
07a0 81 00 60 7b 5f 01 f4 a6 e7 b9 fa 42 09 94 f0 30 60 0e 03 90 1d 80 2e 41 78 be be 10 a0 02 0f c0 ..`{_......B...0`......Ax.......
07c0 60 00 e6 34 04 87 00 28 00 91 32 80 22 cf d4 17 2a 84 54 1b 5b 03 d0 f5 36 8f dd d0 0c e0 00 a4 `..4...(..2."...*.T.[...6.......
07e0 05 d4 6c 4a fa 3b f5 85 04 e2 fa 42 35 12 95 a7 00 5b 60 e8 78 81 24 5d 10 a7 bd 83 96 89 68 4b ..lJ.;.....B5....[`.x.$]......hK
0800 db c8 6e 7d 21 81 b8 be 90 b6 01 5c 5c 40 c9 2f 04 c8 41 c0 30 28 a0 c6 bc 22 67 af be 90 c0 56 ..n}!......\\@./..A.0(..."g....V
0820 7d 21 5d 4b 14 d7 17 12 8e 15 48 52 00 0e 00 4c 02 3e 40 43 f1 9a 44 00 88 f7 b7 00 9b 01 27 cb }!]K......HR...L.>@C..D.......'.
0840 f3 c0 6b 00 44 fb 4f 02 62 40 8d bf 58 5f 48 0b 0c 71 ba be 10 fc 5b f5 85 4c 85 9f 5f 56 5f c8 ..k.D.O.b@..X_H..q....[..L.._V_.
0860 00 7e 63 7d 21 2d 30 04 bf ae be 50 3b 02 c2 ef ab 2f 34 a7 0d f0 5b eb 0b a1 3f f1 7b eb 0b 69 .~c}!-0....P;..../4...[...?.{..i
0880 bc bf be 90 46 af 2f d4 eb 0b f5 d2 24 1d d0 01 1d d0 eb 0b f5 fa 42 bd be 50 af 2f f4 58 7d 21 ....F./.....$.........B..P./.X}!
08a0 4a fc de fa 42 35 93 dd fa 42 7c 6a 7d 21 dd be 53 5f 88 0f ab 2f 64 01 b2 5d 5f 28 c1 27 d6 17 J...B5...B|j}!..S_.../d..]_(.'..
08c0 22 57 40 99 46 b0 f5 bf e3 26 f8 bc fa 42 4c 80 9c cb 90 5a 00 49 01 c9 00 f2 fb ea 0b dd ff 44 "W@.F....&...BL....Z.I.........D
08e0 01 66 00 e0 42 f6 00 ba 5e 08 12 2d 20 93 17 e1 d6 17 ca 39 bf a2 be 90 2e 8a 35 80 c9 77 ef 36 .f..B...^..-.......9......5..w.6
0900 67 07 00 ba 5c 88 16 90 61 b4 82 09 30 d6 ee 4b 3c 5d 5f 28 d7 d8 06 8c 17 32 e3 68 00 69 0a 60 g...\...a...0..K<]_(.....2.h.i.`
0920 5c 15 6e 9a f2 1f cb bf c6 4c ce 33 a0 7e 74 da f2 64 7d a1 9f 2e f2 58 da 1c fd d2 24 dc 08 70 \.n......L.3.~t..d}....X....$..p
0940 b1 00 54 30 4e 02 f8 c9 7f 2c 71 cf 3e 8f 19 66 c0 38 34 5b 72 04 90 63 80 91 da 5c c9 be 00 bc ..T0N....,q.>..f.84[r..c...\....
0960 ea 3c d7 8b 07 10 f0 01 79 9a 01 d7 eb 78 cd b9 a4 aa 80 12 8b 2d 51 7d 21 39 52 d9 23 e7 b9 a3 .<......y....x.......-Q}!9R.#...
0980 61 28 08 0f 90 e0 0a a3 57 dd 86 1a 77 c0 b8 00 40 69 f6 fb 16 d7 7b 92 a3 b4 80 e5 96 fc 1c 80 a(......W...w...@i....{.........
09a0 b9 a3 7b fa 11 e0 fb 9b 8b 0b 98 82 6b 3b 07 b8 1f de d7 ef af af af 92 67 96 02 a0 02 9a 2d 89 ..{.........k;..........g.....-.
09c0 9c 57 80 cb 23 80 65 47 65 76 f9 80 db f6 eb 26 60 5c cf 81 12 5f 7f fe 94 3d 33 20 0a b8 8e e3 .W..#.eGev.....&`\..._...=3.....
09e0 bc 25 c1 59 40 49 9f 5c 9a a3 a6 18 96 e7 f9 f3 f5 3d 3a 00 a1 86 70 1d 14 a0 27 e7 3f b7 00 40 .%.Y@I.\.........=:...p...'.?..@
0a00 4f 42 65 04 be bf ea 5f df 67 80 07 20 02 b0 06 90 f2 ad 39 a0 a4 18 03 be c6 d1 1b 01 e6 b8 8e OBe...._.g.........9............
0a20 e3 fa ab c4 34 02 14 8c c8 02 30 dc c6 1c 44 fd 66 04 0e 02 44 ef 39 e1 9e 62 50 5f 08 6e 07 d8 ....4.....0...D.f...D.9..bP_.n..
0a40 c5 03 38 d7 81 65 4d 93 ef db b8 82 be ca 53 c0 77 f8 5d 42 97 f5 5b 00 2d a0 09 cc 1c d0 4d 72 ..8..eM.......S.w.]B..[.-.....Mr
0a60 03 c0 0e 80 e5 1d 59 ed 8c 72 76 00 ad b2 34 01 86 eb 15 91 2d c0 c5 0a ea ad d5 19 40 e6 7a 25 ......Y..rv...4.....-.......@.z%
0a80 b8 0e f0 03 00 05 5c f4 c8 ba 85 c0 72 59 5f bd 60 a2 21 fe 5b 4c 70 be 0a 5a 00 13 8d 32 0d 47 ......\.....rY_.`.!.[Lp..Z...2.G
0aa0 1f 50 66 84 03 40 40 a3 7d 2a 91 a1 5c 6a eb 65 b8 79 87 55 08 64 d0 70 00 97 3d c0 c0 1c b5 39 .Pf..@@.}*..\j.e.y.U.d.p..=....9
0ac0 bd 12 b7 0d 64 ee f9 8b 3d 84 86 08 50 05 19 c6 5c 10 23 e6 96 6e 84 b2 a5 4e f0 23 00 1c c0 7c ....d...=...P...\.#..n...N.#...|
0ae0 25 2e cd 95 fc 2d 20 65 4a fe 3a 89 dd 72 91 06 30 de 42 9b 5f 02 c6 7a d1 80 02 08 17 63 ac eb %....-.eJ.:..r..0.B._..z.....c..
0b00 0b f9 6b 29 72 f9 ce 55 7a 8f 00 f5 52 c3 66 7d a1 94 f0 6a ab 08 e8 ed 9c 69 00 b2 94 8d d1 62 ..k)r..Uz...R.f}...j.....i.....b
0b20 8c 5d 00 20 64 32 6c 95 e7 49 25 85 ed fa 42 ba 28 0a db bb 02 82 fa 42 27 01 71 7d 21 7b 10 b2 .]..d2l..I%...B.(......B'.q}!{..
0b40 5d 5f 28 71 08 f0 ae fa 42 f6 44 c6 4e 7d 21 3e b3 be 90 2e 2e fc 8d f5 85 94 c0 e5 57 d6 17 d2 ]_(q....B.D.N}!>............W...
0b60 e8 f5 85 7a 7d a1 5e 5f a8 d7 17 ea f5 85 7a 7d a1 5e 5f a8 03 3a a0 03 3a a0 03 3a a0 03 3a a0 ...z}.^_......z}.^_..:..:..:..:.
0b80 03 3a a0 03 3a a0 03 3a a0 03 3a a0 03 3a a0 03 3a a0 03 3a a0 03 3a a0 03 3a a0 03 3a a0 03 3a .:..:..:..:..:..:..:..:..:..:..:
0ba0 a0 03 3a a0 03 3a a0 03 6c fc 03 ad 5f 0b ea df ba 50 29 00 00 00 00 49 45 4e 44 ae 42 60 82 ..:..:..l..._....P)....IEND.B`.
'n628' href='#n628'>628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
/*
 * Secure Remote Password 6a implementation
 * https://github.com/est31/csrp-gmp
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2010, 2013 Tom Cocagne, 2015 est31 <MTest31@outlook.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

// clang-format off
#ifdef WIN32
	#include <windows.h>
	#include <wincrypt.h>
#else
	#include <ctime>

#endif
// clang-format on

#include <cstdlib>
#include <cstring>
#include <cstdio>

#include <config.h>

#if USE_SYSTEM_GMP || defined (__ANDROID__) || defined (ANDROID)
	#include <gmp.h>
#else
	#include <mini-gmp.h>
#endif

#include <util/sha2.h>

#include "srp.h"
//#define CSRP_USE_SHA1
#define CSRP_USE_SHA256

#define srp_dbg_data(data, datalen, prevtext) ;
/*void srp_dbg_data(unsigned char * data, size_t datalen, char * prevtext)
{
	printf(prevtext);
	size_t i;
	for (i = 0; i < datalen; i++)
	{
		printf("%02X", data[i]);
	}
	printf("\n");
}*/

static int g_initialized = 0;

#define RAND_BUFF_MAX 128
static unsigned int g_rand_idx;
static unsigned char g_rand_buff[RAND_BUFF_MAX];

void *(*srp_alloc)(size_t) = &malloc;
void *(*srp_realloc)(void *, size_t) = &realloc;
void (*srp_free)(void *) = &free;

// clang-format off
void srp_set_memory_functions(
		void *(*new_srp_alloc)(size_t),
		void *(*new_srp_realloc)(void *, size_t),
		void (*new_srp_free)(void *))
{
	srp_alloc = new_srp_alloc;
	srp_realloc = new_srp_realloc;
	srp_free = new_srp_free;
}
// clang-format on

typedef struct {
	mpz_t N;
	mpz_t g;
} NGConstant;

struct NGHex {
	const char *n_hex;
	const char *g_hex;
};

/* All constants here were pulled from Appendix A of RFC 5054 */
static struct NGHex global_Ng_constants[] = {
	{/* 1024 */
		"EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C"
		"9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4"
		"8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29"
		"7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A"
		"FD5138FE8376435B9FC61D2FC0EB06E3",
		"2"},
	{/* 2048 */
		"AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC319294"
		"3DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310D"
		"CD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FB"
		"D5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF74"
		"7359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A"
		"436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D"
		"5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E73"
		"03CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB6"
		"94B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F"
		"9E4AFF73",
		"2"},
	{/* 4096 */
		"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
		"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
		"302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
		"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
		"49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
		"FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
		"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
		"180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
		"3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
		"04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
		"B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
		"1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
		"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
		"E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
		"99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
		"04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
		"233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
		"D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
		"FFFFFFFFFFFFFFFF",
		"5"},
	{/* 8192 */
		"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
		"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
		"302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
		"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
		"49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
		"FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
		"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
		"180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
		"3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
		"04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
		"B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
		"1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
		"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
		"E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
		"99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
		"04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
		"233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
		"D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
		"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406"
		"AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918"
		"DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151"
		"2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03"
		"F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F"
		"BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
		"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B"
		"B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632"
		"387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E"
		"6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA"
		"3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C"
		"5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
		"22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC886"
		"2F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6"
		"6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC5"
		"0846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268"
		"359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6"
		"FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"
		"60C980DD98EDD3DFFFFFFFFFFFFFFFFF",
		"13"},
	{0, 0} /* null sentinel */
};

static void delete_ng(NGConstant *ng)
{
	if (ng) {
		mpz_clear(ng->N);
		mpz_clear(ng->g);
		srp_free(ng);
	}
}

static NGConstant *new_ng(SRP_NGType ng_type, const char *n_hex, const char *g_hex)
{
	NGConstant *ng = (NGConstant *)srp_alloc(sizeof(NGConstant));

	if (!ng) return 0;

	mpz_init(ng->N);
	mpz_init(ng->g);

	if (ng_type != SRP_NG_CUSTOM) {
		n_hex = global_Ng_constants[ng_type].n_hex;
		g_hex = global_Ng_constants[ng_type].g_hex;
	}

	int rv = 0;
	rv = mpz_set_str(ng->N, n_hex, 16);
	rv = rv | mpz_set_str(ng->g, g_hex, 16);

	if (rv) {
		delete_ng(ng);
		return 0;
	}

	return ng;
}

typedef union {
	SHA_CTX sha;
	SHA256_CTX sha256;
	// SHA512_CTX sha512;
} HashCTX;

struct SRPVerifier {
	SRP_HashAlgorithm hash_alg;
	NGConstant *ng;

	char *username;
	unsigned char *bytes_B;
	int authenticated;

	unsigned char M[SHA512_DIGEST_LENGTH];
	unsigned char H_AMK[SHA512_DIGEST_LENGTH];
	unsigned char session_key[SHA512_DIGEST_LENGTH];
};

struct SRPUser {
	SRP_HashAlgorithm hash_alg;
	NGConstant *ng;

	mpz_t a;
	mpz_t A;
	mpz_t S;

	unsigned char *bytes_A;
	int authenticated;

	char *username;
	char *username_verifier;
	unsigned char *password;
	size_t password_len;

	unsigned char M[SHA512_DIGEST_LENGTH];
	unsigned char H_AMK[SHA512_DIGEST_LENGTH];
	unsigned char session_key[SHA512_DIGEST_LENGTH];
};

// clang-format off
static int hash_init(SRP_HashAlgorithm alg, HashCTX *c)
{
	switch (alg) {
#ifdef CSRP_USE_SHA1
		case SRP_SHA1: return SHA1_Init(&c->sha);
#endif
		/*
		case SRP_SHA224: return SHA224_Init(&c->sha256);
		*/
#ifdef CSRP_USE_SHA256
		case SRP_SHA256: return SHA256_Init(&c->sha256);
#endif
		/*
		case SRP_SHA384: return SHA384_Init(&c->sha512);
		case SRP_SHA512: return SHA512_Init(&c->sha512);
		*/
		default: return -1;
	};
}
static int hash_update( SRP_HashAlgorithm alg, HashCTX *c, const void *data, size_t len )
{
	switch (alg) {
#ifdef CSRP_USE_SHA1
		case SRP_SHA1: return SHA1_Update(&c->sha, data, len);
#endif
		/*
		case SRP_SHA224: return SHA224_Update(&c->sha256, data, len);
		*/
#ifdef CSRP_USE_SHA256
		case SRP_SHA256: return SHA256_Update(&c->sha256, data, len);
#endif
		/*
		case SRP_SHA384: return SHA384_Update(&c->sha512, data, len);
		case SRP_SHA512: return SHA512_Update(&c->sha512, data, len);
		*/
		default: return -1;
	};
}
static int hash_final( SRP_HashAlgorithm alg, HashCTX *c, unsigned char *md )
{
	switch (alg) {
#ifdef CSRP_USE_SHA1
		case SRP_SHA1: return SHA1_Final(md, &c->sha);
#endif
		/*
		case SRP_SHA224: return SHA224_Final(md, &c->sha256);
		*/
#ifdef CSRP_USE_SHA256
		case SRP_SHA256: return SHA256_Final(md, &c->sha256);
#endif
		/*
		case SRP_SHA384: return SHA384_Final(md, &c->sha512);
		case SRP_SHA512: return SHA512_Final(md, &c->sha512);
		*/
		default: return -1;
	};
}
static unsigned char *hash(SRP_HashAlgorithm alg, const unsigned char *d, size_t n, unsigned char *md)
{
	switch (alg) {
#ifdef CSRP_USE_SHA1
		case SRP_SHA1: return SHA1(d, n, md);
#endif
		/*
		case SRP_SHA224: return SHA224( d, n, md );
		*/
#ifdef CSRP_USE_SHA256
		case SRP_SHA256: return SHA256(d, n, md);
#endif
		/*
		case SRP_SHA384: return SHA384( d, n, md );
		case SRP_SHA512: return SHA512( d, n, md );
		*/
		default: return 0;
	};
}
static size_t hash_length(SRP_HashAlgorithm alg)
{
	switch (alg) {
#ifdef CSRP_USE_SHA1
		case SRP_SHA1: return SHA_DIGEST_LENGTH;
#endif
		/*
		case SRP_SHA224: return SHA224_DIGEST_LENGTH;
		*/
#ifdef CSRP_USE_SHA256
		case SRP_SHA256: return SHA256_DIGEST_LENGTH;
#endif
		/*
		case SRP_SHA384: return SHA384_DIGEST_LENGTH;
		case SRP_SHA512: return SHA512_DIGEST_LENGTH;
		*/
		default: return -1;
	};
}
// clang-format on

inline static int mpz_num_bytes(const mpz_t op)
{
	return (mpz_sizeinbase(op, 2) + 7) / 8;
}

inline static void mpz_to_bin(const mpz_t op, unsigned char *to)
{
	mpz_export(to, NULL, 1, 1, 1, 0, op);
}

inline static void mpz_from_bin(const unsigned char *s, size_t len, mpz_t ret)
{
	mpz_import(ret, len, 1, 1, 1, 0, s);
}

// set op to (op1 * op2) mod d, using tmp for the calculation
inline static void mpz_mulm(
	mpz_t op, const mpz_t op1, const mpz_t op2, const mpz_t d, mpz_t tmp)
{
	mpz_mul(tmp, op1, op2);
	mpz_mod(op, tmp, d);
}

// set op to (op1 + op2) mod d, using tmp for the calculation
inline static void mpz_addm(
	mpz_t op, const mpz_t op1, const mpz_t op2, const mpz_t d, mpz_t tmp)
{
	mpz_add(tmp, op1, op2);
	mpz_mod(op, tmp, d);
}

// set op to (op1 - op2) mod d, using tmp for the calculation
inline static void mpz_subm(
	mpz_t op, const mpz_t op1, const mpz_t op2, const mpz_t d, mpz_t tmp)
{
	mpz_sub(tmp, op1, op2);
	mpz_mod(op, tmp, d);
}

static SRP_Result H_nn(
	mpz_t result, SRP_HashAlgorithm alg, const mpz_t N, const mpz_t n1, const mpz_t n2)
{
	unsigned char buff[SHA512_DIGEST_LENGTH];
	size_t len_N = mpz_num_bytes(N);
	size_t len_n1 = mpz_num_bytes(n1);
	size_t len_n2 = mpz_num_bytes(n2);
	size_t nbytes = len_N + len_N;
	unsigned char *bin = (unsigned char *)srp_alloc(nbytes);
	if (!bin) return SRP_ERR;
	if (len_n1 > len_N || len_n2 > len_N) {
		srp_free(bin);
		return SRP_ERR;
	}
	memset(bin, 0, nbytes);
	mpz_to_bin(n1, bin + (len_N - len_n1));
	mpz_to_bin(n2, bin + (len_N + len_N - len_n2));
	hash(alg, bin, nbytes, buff);
	srp_free(bin);
	mpz_from_bin(buff, hash_length(alg), result);
	return SRP_OK;
}

static SRP_Result H_ns(mpz_t result, SRP_HashAlgorithm alg, const unsigned char *n,
	size_t len_n, const unsigned char *bytes, size_t len_bytes)
{
	unsigned char buff[SHA512_DIGEST_LENGTH];
	size_t nbytes = len_n + len_bytes;
	unsigned char *bin = (unsigned char *)srp_alloc(nbytes);
	if (!bin) return SRP_ERR;
	memcpy(bin, n, len_n);
	memcpy(bin + len_n, bytes, len_bytes);
	hash(alg, bin, nbytes, buff);
	srp_free(bin);
	mpz_from_bin(buff, hash_length(alg), result);
	return SRP_OK;
}

static int calculate_x(mpz_t result, SRP_HashAlgorithm alg, const unsigned char *salt,
	size_t salt_len, const char *username, const unsigned char *password,
	size_t password_len)
{
	unsigned char ucp_hash[SHA512_DIGEST_LENGTH];
	HashCTX ctx;
	hash_init(alg, &ctx);

	srp_dbg_data((char *)username, strlen(username), "Username for x: ");
	srp_dbg_data((char *)password, password_len, "Password for x: ");
	hash_update(alg, &ctx, username, strlen(username));
	hash_update(alg, &ctx, ":", 1);
	hash_update(alg, &ctx, password, password_len);

	hash_final(alg, &ctx, ucp_hash);

	return H_ns(result, alg, salt, salt_len, ucp_hash, hash_length(alg));
}

static SRP_Result update_hash_n(SRP_HashAlgorithm alg, HashCTX *ctx, const mpz_t n)
{
	size_t len = mpz_num_bytes(n);
	unsigned char *n_bytes = (unsigned char *)srp_alloc(len);
	if (!n_bytes) return SRP_ERR;
	mpz_to_bin(n, n_bytes);
	hash_update(alg, ctx, n_bytes, len);
	srp_free(n_bytes);
	return SRP_OK;
}

static SRP_Result hash_num(SRP_HashAlgorithm alg, const mpz_t n, unsigned char *dest)
{
	int nbytes = mpz_num_bytes(n);
	unsigned char *bin = (unsigned char *)srp_alloc(nbytes);
	if (!bin) return SRP_ERR;
	mpz_to_bin(n, bin);
	hash(alg, bin, nbytes, dest);
	srp_free(bin);
	return SRP_OK;
}

static SRP_Result calculate_M(SRP_HashAlgorithm alg, NGConstant *ng, unsigned char *dest,
	const char *I, const unsigned char *s_bytes, size_t s_len, const mpz_t A,
	const mpz_t B, const unsigned char *K)
{
	unsigned char H_N[SHA512_DIGEST_LENGTH];
	unsigned char H_g[SHA512_DIGEST_LENGTH];
	unsigned char H_I[SHA512_DIGEST_LENGTH];
	unsigned char H_xor[SHA512_DIGEST_LENGTH];
	HashCTX ctx;
	size_t i = 0;
	size_t hash_len = hash_length(alg);

	if (!hash_num(alg, ng->N, H_N)) return SRP_ERR;
	if (!hash_num(alg, ng->g, H_g)) return SRP_ERR;

	hash(alg, (const unsigned char *)I, strlen(I), H_I);

	for (i = 0; i < hash_len; i++)
		H_xor[i] = H_N[i] ^ H_g[i];

	hash_init(alg, &ctx);

	hash_update(alg, &ctx, H_xor, hash_len);
	hash_update(alg, &ctx, H_I, hash_len);
	hash_update(alg, &ctx, s_bytes, s_len);
	if (!update_hash_n(alg, &ctx, A)) return SRP_ERR;
	if (!update_hash_n(alg, &ctx, B)) return SRP_ERR;
	hash_update(alg, &ctx, K, hash_len);

	hash_final(alg, &ctx, dest);
	return SRP_OK;
}

static SRP_Result calculate_H_AMK(SRP_HashAlgorithm alg, unsigned char *dest,
	const mpz_t A, const unsigned char *M, const unsigned char *K)
{
	HashCTX ctx;

	hash_init(alg, &ctx);

	if (!update_hash_n(alg, &ctx, A)) return SRP_ERR;
	hash_update(alg, &ctx, M, hash_length(alg));
	hash_update(alg, &ctx, K, hash_length(alg));

	hash_final(alg, &ctx, dest);
	return SRP_OK;
}

static SRP_Result fill_buff()
{
	g_rand_idx = 0;

#ifdef WIN32
	HCRYPTPROV wctx;
#else
	FILE *fp = 0;
#endif

#ifdef WIN32

	if (!CryptAcquireContext(&wctx, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
		return SRP_ERR;
	if (!CryptGenRandom(wctx, sizeof(g_rand_buff), (BYTE *)g_rand_buff)) return SRP_ERR;
	if (!CryptReleaseContext(wctx, 0)) return SRP_ERR;

#else
	fp = fopen("/dev/urandom", "r");

	if (!fp) return SRP_ERR;

	if (fread(g_rand_buff, sizeof(g_rand_buff), 1, fp) != 1) { fclose(fp); return SRP_ERR; }
	if (fclose(fp)) return SRP_ERR;
#endif
	return SRP_OK;
}

static SRP_Result mpz_fill_random(mpz_t num)
{
	// was call: BN_rand(num, 256, -1, 0);
	if (RAND_BUFF_MAX - g_rand_idx < 32)
		if (fill_buff() != SRP_OK) return SRP_ERR;
	mpz_from_bin((const unsigned char *)(&g_rand_buff[g_rand_idx]), 32, num);
	g_rand_idx += 32;
	return SRP_OK;
}

static SRP_Result init_random()
{
	if (g_initialized) return SRP_OK;
	SRP_Result ret = fill_buff();
	g_initialized = (ret == SRP_OK);
	return ret;
}

#define srp_dbg_num(num, text) ;
/*void srp_dbg_num(mpz_t num, char * prevtext)
{
	int len_num = mpz_num_bytes(num);
	char *bytes_num = (char*) srp_alloc(len_num);
	mpz_to_bin(num, (unsigned char *) bytes_num);
	srp_dbg_data(bytes_num, len_num, prevtext);
	srp_free(bytes_num);

}*/

/***********************************************************************************************************
 *
 *  Exported Functions
 *
 ***********************************************************************************************************/

// clang-format off
SRP_Result srp_create_salted_verification_key( SRP_HashAlgorithm alg,
	SRP_NGType ng_type, const char *username_for_verifier,
	const unsigned char *password, size_t len_password,
	unsigned char **bytes_s,  size_t *len_s,
	unsigned char **bytes_v, size_t *len_v,
	const char *n_hex, const char *g_hex )
{
	SRP_Result ret = SRP_OK;

	mpz_t v; mpz_init(v);
	mpz_t x; mpz_init(x);
	// clang-format on

	NGConstant *ng = new_ng(ng_type, n_hex, g_hex);

	if (!ng) goto error_and_exit;

	if (init_random() != SRP_OK) /* Only happens once */
		goto error_and_exit;

	if (*bytes_s == NULL) {
		size_t size_to_fill = 16;
		*len_s = size_to_fill;
		if (RAND_BUFF_MAX - g_rand_idx < size_to_fill)
			if (fill_buff() != SRP_OK) goto error_and_exit;
		*bytes_s = (unsigned char *)srp_alloc(size_to_fill);
		if (!*bytes_s) goto error_and_exit;
		memcpy(*bytes_s, &g_rand_buff + g_rand_idx, size_to_fill);
		g_rand_idx += size_to_fill;
	}

	if (!calculate_x(
			x, alg, *bytes_s, *len_s, username_for_verifier, password, len_password))
		goto error_and_exit;

	srp_dbg_num(x, "Server calculated x: ");

	mpz_powm(v, ng->g, x, ng->N);

	*len_v = mpz_num_bytes(v);

	*bytes_v = (unsigned char *)srp_alloc(*len_v);

	if (!*bytes_v) goto error_and_exit;

	mpz_to_bin(v, *bytes_v);

cleanup_and_exit:
	delete_ng(ng);
	mpz_clear(v);
	mpz_clear(x);
	return ret;
error_and_exit:
	ret = SRP_ERR;
	goto cleanup_and_exit;
}

// clang-format off

/* Out: bytes_B, len_B.
 *
 * On failure, bytes_B will be set to NULL and len_B will be set to 0
 */
struct SRPVerifier *srp_verifier_new(SRP_HashAlgorithm alg,
	SRP_NGType ng_type, const char *username,
	const unsigned char *bytes_s, size_t len_s,
	const unsigned char *bytes_v, size_t len_v,
	const unsigned char *bytes_A, size_t len_A,
	const unsigned char *bytes_b, size_t len_b,
	unsigned char **bytes_B, size_t *len_B,
	const char *n_hex, const char *g_hex )
{
	mpz_t v; mpz_init(v); mpz_from_bin(bytes_v, len_v, v);
	mpz_t A; mpz_init(A); mpz_from_bin(bytes_A, len_A, A);
	mpz_t u; mpz_init(u);
	mpz_t B; mpz_init(B);
	mpz_t S; mpz_init(S);
	mpz_t b; mpz_init(b);
	mpz_t k; mpz_init(k);
	mpz_t tmp1; mpz_init(tmp1);
	mpz_t tmp2; mpz_init(tmp2);
	mpz_t tmp3; mpz_init(tmp3);
	// clang-format on
	size_t ulen = strlen(username) + 1;
	NGConstant *ng = new_ng(ng_type, n_hex, g_hex);
	struct SRPVerifier *ver = 0;

	*len_B = 0;
	*bytes_B = 0;

	if (!ng) goto cleanup_and_exit;

	ver = (struct SRPVerifier *)srp_alloc(sizeof(struct SRPVerifier));

	if (!ver) goto cleanup_and_exit;

	if (init_random() != SRP_OK) { /* Only happens once */
		srp_free(ver);
		ver = 0;
		goto cleanup_and_exit;
	}

	ver->username = (char *)srp_alloc(ulen);
	ver->hash_alg = alg;
	ver->ng = ng;

	if (!ver->username) {
		srp_free(ver);
		ver = 0;
		goto cleanup_and_exit;
	}

	memcpy(ver->username, username, ulen);

	ver->authenticated = 0;

	/* SRP-6a safety check */
	mpz_mod(tmp1, A, ng->N);
	if (mpz_sgn(tmp1) != 0) {
		if (bytes_b) {
			mpz_from_bin(bytes_b, len_b, b);
		} else {
			if (!mpz_fill_random(b)) goto ver_cleanup_and_exit;
		}

		if (!H_nn(k, alg, ng->N, ng->N, ng->g)) goto ver_cleanup_and_exit;

		/* B = kv + g^b */
		mpz_mulm(tmp1, k, v, ng->N, tmp3);
		mpz_powm(tmp2, ng->g, b, ng->N);
		mpz_addm(B, tmp1, tmp2, ng->N, tmp3);

		if (!H_nn(u, alg, ng->N, A, B)) goto ver_cleanup_and_exit;

		srp_dbg_num(u, "Server calculated u: ");

		/* S = (A *(v^u)) ^ b */
		mpz_powm(tmp1, v, u, ng->N);
		mpz_mulm(tmp2, A, tmp1, ng->N, tmp3);
		mpz_powm(S, tmp2, b, ng->N);

		if (!hash_num(alg, S, ver->session_key)) goto ver_cleanup_and_exit;

		if (!calculate_M(
				alg, ng, ver->M, username, bytes_s, len_s, A, B, ver->session_key)) {
			goto ver_cleanup_and_exit;
		}
		if (!calculate_H_AMK(alg, ver->H_AMK, A, ver->M, ver->session_key)) {
			goto ver_cleanup_and_exit;
		}

		*len_B = mpz_num_bytes(B);
		*bytes_B = (unsigned char *)srp_alloc(*len_B);

		if (!*bytes_B) {
			*len_B = 0;
			goto ver_cleanup_and_exit;
		}

		mpz_to_bin(B, *bytes_B);

		ver->bytes_B = *bytes_B;
	} else {
		srp_free(ver);
		ver = 0;
	}

cleanup_and_exit:
	mpz_clear(v);
	mpz_clear(A);
	mpz_clear(u);
	mpz_clear(k);
	mpz_clear(B);
	mpz_clear(S);
	mpz_clear(b);
	mpz_clear(tmp1);
	mpz_clear(tmp2);