/src/ghostpdl/base/smd5.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* MD5Encode filter */ |
18 | | #include "memory_.h" |
19 | | #include "strimpl.h" |
20 | | #include "stream.h" |
21 | | #include "smd5.h" |
22 | | |
23 | | /* ------ MD5Encode ------ */ |
24 | | |
25 | | private_st_MD5E_state(); |
26 | | |
27 | | /* Initialize the state. */ |
28 | | static int |
29 | | s_MD5E_init(stream_state * st) |
30 | 0 | { |
31 | 0 | stream_MD5E_state *const ss = (stream_MD5E_state *) st; |
32 | |
|
33 | 0 | gs_md5_init(&ss->md5); |
34 | 0 | return 0; |
35 | 0 | } |
36 | | |
37 | | /* Process a buffer. */ |
38 | | static int |
39 | | s_MD5E_process(stream_state * st, stream_cursor_read * pr, |
40 | | stream_cursor_write * pw, bool last) |
41 | 0 | { |
42 | 0 | stream_MD5E_state *const ss = (stream_MD5E_state *) st; |
43 | 0 | int status = 0; |
44 | |
|
45 | 0 | if (pr->ptr < pr->limit) { |
46 | 0 | gs_md5_append(&ss->md5, pr->ptr + 1, pr->limit - pr->ptr); |
47 | 0 | pr->ptr = pr->limit; |
48 | 0 | } |
49 | 0 | if (last) { |
50 | 0 | if (pw->limit - pw->ptr >= 16) { |
51 | 0 | gs_md5_finish(&ss->md5, pw->ptr + 1); |
52 | 0 | pw->ptr += 16; |
53 | 0 | status = EOFC; |
54 | 0 | } else |
55 | 0 | status = 1; |
56 | 0 | } |
57 | 0 | return status; |
58 | 0 | } |
59 | | |
60 | | /* Stream template */ |
61 | | const stream_template s_MD5E_template = { |
62 | | &st_MD5E_state, s_MD5E_init, s_MD5E_process, 1, 16 |
63 | | }; |
64 | | |
65 | | stream * |
66 | | s_MD5E_make_stream(gs_memory_t *mem, byte *digest, int digest_size) |
67 | 0 | { |
68 | 0 | stream *s = s_alloc(mem, "s_MD5E_make_stream"); |
69 | 0 | stream_state *ss = s_alloc_state(mem, s_MD5E_template.stype, "s_MD5E_make_stream"); |
70 | |
|
71 | 0 | if (ss == NULL || s == NULL) |
72 | 0 | goto err; |
73 | 0 | ss->templat = &s_MD5E_template; |
74 | 0 | if (s_init_filter(s, ss, digest, digest_size, NULL) < 0) |
75 | 0 | goto err; |
76 | 0 | s->strm = s; |
77 | 0 | return s; |
78 | 0 | err: |
79 | 0 | gs_free_object(mem, ss, "s_MD5E_make_stream"); |
80 | 0 | gs_free_object(mem, s, "s_MD5E_make_stream"); |
81 | 0 | return NULL; |
82 | 0 | } |
83 | | |
84 | | /* Process a buffer. */ |
85 | | static int |
86 | | s_MD5C_process(stream_state * st, stream_cursor_read * pr, |
87 | | stream_cursor_write * pw, bool last) |
88 | 0 | { |
89 | 0 | stream_MD5E_state *const ss = (stream_MD5E_state *) st; |
90 | 0 | int nr = pr->limit - pr->ptr; |
91 | 0 | int nw = pw->limit - pw->ptr; |
92 | 0 | int n = min(nr, nw); |
93 | |
|
94 | 0 | gs_md5_append(&ss->md5, pr->ptr + 1, n); |
95 | 0 | memcpy(pw->ptr + 1, pr->ptr + 1, n); |
96 | 0 | pr->ptr += n; |
97 | 0 | pw->ptr += n; |
98 | 0 | if (pw->limit == pw->ptr) |
99 | 0 | return 1; |
100 | 0 | return 0; |
101 | 0 | } |
102 | | /* Stream template */ |
103 | | const stream_template s_MD5C_template = { |
104 | | &st_MD5E_state, s_MD5E_init, s_MD5C_process, 1, 1024 |
105 | | }; |
106 | | |
107 | | stream * |
108 | | s_MD5C_make_stream(gs_memory_t *mem, stream *strm) |
109 | 0 | { |
110 | 0 | stream *s = s_alloc(mem, "s_MD5E_make_stream"); |
111 | 0 | stream_state *ss = s_alloc_state(mem, s_MD5E_template.stype, "s_MD5E_make_stream"); |
112 | 0 | int buffer_size = 1024; |
113 | 0 | byte *buffer = gs_alloc_bytes(mem, buffer_size, "s_MD5E_make_stream(buffer)"); |
114 | |
|
115 | 0 | if (ss == NULL || s == NULL || buffer == NULL) |
116 | 0 | goto err; |
117 | 0 | ss->templat = &s_MD5C_template; |
118 | 0 | if (s_init_filter(s, ss, buffer, buffer_size, NULL) < 0) |
119 | 0 | goto err; |
120 | 0 | s->strm = strm; |
121 | 0 | s->close_strm = true; |
122 | 0 | return s; |
123 | 0 | err: |
124 | 0 | gs_free_object(mem, ss, "s_MD5E_make_stream"); |
125 | 0 | gs_free_object(mem, s, "s_MD5E_make_stream"); |
126 | 0 | gs_free_object(mem, buffer, "s_MD5E_make_stream"); |
127 | 0 | return NULL; |
128 | 0 | } |
129 | | |
130 | | /* Get a digest. Apply 'flush' before calling. */ |
131 | | int |
132 | | s_MD5C_get_digest(stream *s, byte *buf, int buf_length) |
133 | 0 | { |
134 | 0 | stream_MD5E_state *const ss = (stream_MD5E_state *)s->state; |
135 | 0 | gs_md5_state_t md5; |
136 | 0 | byte b[16], *p; |
137 | 0 | int l = min(16, buf_length), k; |
138 | |
|
139 | 0 | if (s->procs.process != s_MD5C_process) |
140 | 0 | return 0; /* Must not happen. */ |
141 | 0 | md5 = ss->md5; |
142 | 0 | gs_md5_finish(&md5, b); |
143 | 0 | memcpy(buf, b, l); |
144 | 0 | for (p = b + l; p < b + sizeof(b); p += l) { |
145 | 0 | for (k = 0; k < l && p + k < b + sizeof(b); k++) |
146 | 0 | buf[k] ^= p[k]; |
147 | 0 | } |
148 | 0 | return l; |
149 | 0 | } |