#include <stdbool.h>
 #include <stdint.h>
+#include <string.h>
 
 #include "atom.h"
 #include "frombe.h"
 #include "schema.h"
 
 static const char CmdEach[] = "*";
+static const char CmdEq[] = "=";
 static const char CmdExists[] = "E";
 static const char CmdGT[] = ">";
 static const char CmdLT[] = "<";
         }
         err.msg = "TAKE";
         err.code = KEKSSchemaErrNo;
+    } else if (KEKSStrEqual(&(schema->list[idxSchema].atom), CmdEq)) {
+        err.msg = "EQ";
+        if ((*taken) == SIZE_MAX) {
+            err.code = KEKSSchemaErrNo;
+        } else {
+            idxSchema = schema->list[idxSchema].next;
+            if (idxSchema == 0) {
+                err.code = KEKSSchemaErrInvalidSchema;
+                err.msg = "wrong number of args";
+                return err;
+            }
+            err.offSchema = schema->offsets[idxSchema];
+            if (schema->list[idxSchema].atom.typ != KEKSItemStr) {
+                err.code = KEKSSchemaErrInvalidSchema;
+                err.msg = "non-str EQ";
+                return err;
+            }
+            err.code = ((schema->list[idxSchema].atom.v.str.len ==
+                         data->list[*taken].atom.v.str.len) &&
+                        (memcmp(
+                             schema->list[idxSchema].atom.v.str.ptr,
+                             data->list[*taken].atom.v.str.ptr,
+                             schema->list[idxSchema].atom.v.str.len) == 0)) ?
+                           KEKSSchemaErrNo :
+                           KEKSSchemaErrInvalidData;
+        }
     } else if (KEKSStrEqual(&(schema->list[idxSchema].atom), CmdEach)) {
         err.msg = "EACH";
         (*eachInList) = false;
 
 
 const (
        CmdEach        = "*"
+       CmdEq          = "="
        CmdExists      = "E"
        CmdGT          = ">"
        CmdLT          = "<"
                        default:
                                return fmt.Errorf("%s: %d: %s: non-iterable", schemaName, i, cmd)
                        }
+               case CmdEq:
+                       if vs == nil {
+                               continue
+                       }
+                       if len(act) != 2 {
+                               return fmt.Errorf("%s: %d: %s: wrong number of args", schemaName, i, cmd)
+                       }
+                       expect, ok := act[1].(string)
+                       if !ok {
+                               return fmt.Errorf("%s: %d: %s: bad str: %+v", schemaName, i, cmd, act[1])
+                       }
+                       for _, v := range vs {
+                               got, ok := v.(string)
+                               if !ok {
+                                       return fmt.Errorf("%s: %d: %s: not str: %T", schemaName, i, cmd, v)
+                               }
+                               if got != expect {
+                                       return fmt.Errorf("%s: %d: %s: !=", schemaName, i, cmd)
+                               }
+                       }
                case CmdType:
                        if vs == nil {
                                continue
                        if vs == nil {
                                continue
                        }
-                       var expect int64
                        if len(act) != 2 {
                                return fmt.Errorf("%s: %d: %s: wrong number of args", schemaName, i, cmd)
                        }
+                       var expect int64
                        switch v := act[1].(type) {
                        case uint64:
                                expect = int64(v)
 
     @item 18 -- up to attoseconds;
     @end itemize
 
+@item = v
+Check that chosen (if it exists) string element's value equals to "v".
+
 @end table
 
 For example let's check "our" structure, described in CDDL as:
 
 @item IS-SET k
 Check that "k" is non-empty set (map with NIL values).
 
+@item STR= k v
+Check that "k" is a string with value "v".
+
 @end table
 
 proc EXISTS {} {return {{LIST {{STR E}}}}}
 proc !EXISTS {} {return {{LIST {{STR !E}}}}}
 proc EACH {} {return {{LIST {{STR *}}}}}
+proc EQ {v} {subst {{LIST {{STR =} {STR $v}}}}}
 proc TYPE {vs} {
     set l {{STR T}}
     foreach v $vs {
     }]
 }
 
+proc STR= {k v} {
+    evals [subst {
+        {TAKE $k}
+        {TYPE {STR}}
+        {TAKE $k}
+        {EQ $v}
+    }]
+}
+
 proc LEN= {k l} {
     evals [subst {
         {TAKE $k}
 
 
 kem-balloon-blake2b-hkdf {
     {HAS a}
-    {TYPE= a {STR}}
-    {!EMPTY a}
+    {STR= a balloon-blake2b-hkdf}
     {HAS cek}
     {TYPE= cek {BIN}}
     {HAS salt}
 
 
 load {
     {HAS t}
-    {TYPE= t {STR}}
-    {!EMPTY t}
+    {STR= t pub}
     {HAS v}
     {SCHEMA= v pub-load}
 }